home *** CD-ROM | disk | FTP | other *** search
/ Internet Tools (InfoMagic) / Internet Tools.iso / news / readers / nnmvs / distrib.cntl.v3r1.Z / distrib.cntl.v3r1
Text File  |  1995-04-24  |  1MB  |  30,015 lines

  1. //JOBNAME  JOB ACCOUNT,'NAME'
  2. //*------------------------------------------------------------------*/
  3. //*                                                                  */
  4. //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  5. //*                                                                  */
  6. //* This software is provided on an "AS IS" basis.  All warranties,  */
  7. //* including the implied warranties of merchantability and fitness, */
  8. //* are expressly denied.                                            */
  9. //*                                                                  */
  10. //* Provided this copyright notice is included, this software may    */
  11. //* be freely distributed and not offered for sale.                  */
  12. //*                                                                  */
  13. //* Changes or modifications may be made and used only by the maker  */
  14. //* of same, and not further distributed.  Such modifications should */
  15. //* be mailed to the author for consideration for addition to the    */
  16. //* software and incorporation in subsequent releases.               */
  17. //*                                                                  */
  18. //*------------------------------------------------------------------*/
  19. //*
  20. //* NNMVS - NNTP Client News Reader for MVS/ISPF - Version 3 Release 1
  21. //*
  22. //* Author:  Steve Bacher <seb1525@mvs.draper.com>
  23. //*
  24. //* Date:  March, 1993
  25. //*
  26. //*--------------------------------------------------------------------
  27. //*
  28. //* This job creates the NNMVS distribution libraries (PDS's).
  29. //*
  30. //* Run this JCL to create the PDS's, after customizing to suit.
  31. //* (Obviously, put in a good JOB statement first.)
  32. //* To customize the JCL, change the defaults on the //NNLOAD PROC
  33. //* statement to your liking, particularly the PREFIX default.
  34. //* You might also want to change the final qualifiers of the PDS's
  35. //* created - to do this, find the // EXEC NNLOAD statements and
  36. //* change the value of the TO parameter.
  37. //*
  38. //* See the $$README file (of the CNTL PDS, first in this stream)
  39. //* for the rest of the installation instructions.
  40. //*
  41. //NNLOAD  PROC CLS='*',BS='6160',U='3380',V='',
  42. //             TRK1='30',TRK2='10',DIR='35',RLSE='RLSE',
  43. //             PREFIX='NNMVS.INSTALL.'
  44. //*
  45. //IEBUPDTE EXEC PGM=IEBUPDTE,PARM=NEW
  46. //SYSPRINT DD   SYSOUT=&CLS
  47. //SYSUT2   DD   DISP=(NEW,CATLG,DELETE),DSN=&PREFIX.&TO,
  48. //         DCB=(RECFM=FB,LRECL=80,BLKSIZE=&BS),
  49. //         SPACE=(TRK,(&TRK1,&TRK2,&DIR),&RLSE),UNIT=&U,VOL=SER=&V
  50. //*
  51. //         PEND
  52. //CNTL     EXEC NNLOAD,TRK1='5',TO='CNTL'
  53. //SYSIN    DD DATA,DLM='?!'
  54. ./   ADD NAME=$$README,SSI=012C0002
  55.  
  56. ------------------------------------------------------------------------
  57.  
  58.  Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992
  59.  
  60.  SAS enhancements copyright (c) 1992 SAS Institute, Inc.
  61.  
  62.  This software is provided on an "AS IS" basis.  All warranties,
  63.  including the implied warranties of merchantability and fitness,
  64.  are expressly denied.
  65.  
  66.  Provided this copyright notice is included, this software may
  67.  be freely distributed and not offered for sale.
  68.  
  69.  Changes or modifications may be made and used only by the maker
  70.  of same, and not further distributed.  Such modifications should
  71.  be mailed to the author for consideration for addition to the
  72.  software and incorporation in subsequent releases.
  73.  
  74. ------------------------------------------------------------------------
  75.  
  76.  MVS NNTP News Reader - Version 3 Release 1
  77.  
  78.  Author:          Steve Bacher <seb1525@mvs.draper.com>
  79.  Enhancements by: Dale Ingold  <snoddi@mvs.sas.com>
  80.  
  81. ------------------------------------------------------------------------
  82.  
  83.  New Features and Changes in member $CHANGES of the distribution.
  84.  
  85. ------------------------------------------------------------------------
  86.  
  87.  Contents of PDS's belonging to NNMVS distribution:
  88.  
  89.  Member     PDS Type    Description
  90.  
  91.  $$README   CNTL        This file
  92.  $CHANGES   CNTL        New features and changes
  93.  $MISC      CNTL        Miscellaneous gotchas and installation notes
  94.  ALLOAD     CNTL        JCL to allocate NNMVS load library
  95.  AUTH       CNTL        Sample server authorization file
  96.  COMPILE    CNTL        JCL to compile and link C source
  97.  GRAMMAR    CNTL        Description of NNMVS batch expression syntax
  98.  HELP       CNTL        Description of NNMVS batch language
  99.  NNMVS      CNTL        JCL to run NNMVS in batch
  100.  NNMVSHLP   CNTL        TSO HELP for the NNMVSP version of the exec
  101.  NNMFIUCV   CLIST       Exec to check for multiple socket applications
  102.  NNMVS      CLIST       Exec by which users invoke the news reader
  103.  NNMVSC     CLIST       CLIST by which users invoke the news reader
  104.  NNMVSL     CLIST       CLIST to run multiple-news-server ISPF dialog
  105.  NNMVSP     CLIST       Exec using XPROC to parse CLIST-style parms
  106.  NNMMAIL    CLIST       Exec called by news reader to send mail
  107.  NNM...     PANEL       ISPF regular panels
  108.  TNNM...    PANEL       ISPF tutorial panels
  109.  NN...      H           C headers for compilation
  110.  NNM...     C           C source for compilation
  111.  
  112. --------------------------------------------------------------------
  113.  
  114.  Directions:
  115.  
  116.  Assuming the PDS's have been created:
  117.  
  118.  1. Customize the ALLOAD and COMPILE JCL members to reflect your
  119.  local conventions.  Note:  If you intend to place the executable into
  120.  an existing library, you can suppress that part of the ALLOAD JCL.
  121.  The name of the data set created must match across both members.
  122.  
  123.  2. Customize the NNUSER header file as shown by the comments therein.
  124.  Note in particular the defines for your TCP/IP and your C compiler.
  125.  There are changes to the linkedit JCL that are related to these.
  126.  
  127.  3. Choose which exec you want to use:
  128.  
  129.     NNMVS - the traditional REXX exec, not much parameter passing
  130.     NNMVSP - REXX exec that uses XPROC to parse CLIST-style parms
  131.     NNMVSC - CLIST that accepts CLIST-style parameters
  132.  
  133.  If you don't have XPROC (the utility that allows a REXX exec to parse
  134.  CLIST-style parameters), you can get it from the same place that you
  135.  got NNMVS.  I highly recommend that you do so if you do a lot of
  136.  conversion from CLIST to REXX.
  137.  
  138.  If you really can't or won't get XPROC, you can use the CLIST, but
  139.  keep in mind that there are some things the CLIST just can't do that
  140.  the REXX exec can.  Refer to the comments therein for more details.
  141.  
  142.  Customize whichever of the above you pick to define the names of the
  143.  MVS libraries to contain the panel and load library members.  The load
  144.  library must be the one specified in the ALLOAD JCL, if you are
  145.  creating it anew.  Observe the comments relating to the use of LIBDEF
  146.  and ISPF APPLIDs.
  147.  
  148.  Note that if you install one of the REXX execs, you must also install
  149.  the NNMFIUCV exec in the same library.  This exec implements a crude
  150.  check for an existing TCP/IP socket application (e.g. another NNMVS)
  151.  in a different PIE MultiTSO session.  It prevents your users from
  152.  crashing TCP/IP, so it is highly recommended that you make use of it.
  153.  
  154.  4. Customize the NNMMAIL exec to invoke your local mailer, or
  155.  otherwise insure that messages sent via MAIL or REPLY arrive at their
  156.  intended destination.
  157.  
  158.  5. If you are running ISPF Version 2 or earlier, edit the NNMVS panels
  159.  whose names begin "NNMP...".  These are popups, and will not work
  160.  under ISPF Version 2 unless you change the )BODY line.  Remove the
  161.  WINDOW(...) parameter from the )BODY line of each panel so that the
  162.  line just says )BODY or )BODY EXPAND(``), as the case may be.
  163.  
  164.  Note:  You may wish to customize the TNNMSERV tutorial panel to
  165.  include the names of all available NNTP servers at your site.
  166.  
  167.  Now, to install:
  168.  
  169.  6. Submit the ALLOAD JCL to allocate the load library from which the
  170.  executable program will be run.  If you intend to place the executable
  171.  into an existing library, you can skip this step, but you should make
  172.  sure that there is no previous load module named NNMMAIN in the load
  173.  library of your choice before you proceed.
  174.  
  175.  7. Submit the COMPILE JCL to compile all the C sources and create the
  176.  executable NNMVS load module.
  177.  
  178.  The first time you run this you can expect a return code of 8 from
  179.  the linkedit.  Like SMP/E, this is OK if the only reason is an IEW0342
  180.  because the "INCLUDE SYSLMOD(NNMMAIN)" did not find an existing load
  181.  module.  If you get IEW0132 (unresolved external reference) or
  182.  IEW0241 (ESD type definition conflict), your linkedit went awry.
  183.  Don't use the resultant load module.  Check the libraries you
  184.  specified on the link step to see what went wrong.
  185.  
  186.  In the future, if you have to recompile individual modules, you can use
  187.  the same JCL to compile only those modules, and the link will include
  188.  the new modules in the existing executable load module.
  189.  
  190.  *********************************************************************
  191.  
  192.  IMPORTANT:  If you are running TCP/IP V2R2 or higher on MVS, you must
  193.  change the following library names in the compile and link JCL:
  194.  
  195.    TCPIP.COMMMAC   should be changed to  TCPIP.SEZACMAC
  196.    TCPIP.COMMTXT   should be changed to  TCPIP.SEZACMTX
  197.  
  198.  *********************************************************************
  199.  
  200.  Note:  If you have defined C370V1 in the NNUSER header file, you must
  201.  also include the system linklist load library or libraries containing
  202.  ISPLINK, ISPEXEC and IKJEFF18 when linking.  Otherwise you may delete
  203.  the lines from the linkedit JCL that reference them.
  204.  
  205.  Note:  You need not include the PASCAL libraries or the AMPZMVSB
  206.  module if you are using TCP/IP Version 2 or higher, in which case
  207.  you must also define TCPIPV2 in the NNUSER headerfile.
  208.  
  209.  8. Copy the HELP member of the CNTL library into the data set which
  210.  will be allocated to ddname NNBATHLP by the NNMVS batch mode JCL
  211.  procedure.  This data set contains the text printed by the batch HELP
  212.  command.  The distributed proc calls this 'NNMVS.HELP' - change it to
  213.  match the name of your data set (sequential, or member of a PDS).
  214.  
  215.  9. Copy the NNMVS (or NNMVSC or NNMVSP) and NNMMAIL execs into your
  216.  installation CLIST or REXX library.  Also copy the NNMVSL exec if
  217.  you want access to Leonard Woren's experimental multiple-server dialog.
  218.  
  219.  10. If you use the NNMVSP version of the exec, copy the NNMVSHLP
  220.  member of the CNTL PDS into your installation TSO HELP library
  221.  under the same name as you gave the exec, so folks can type HELP xxx
  222.  where xxx is the name of the exec.  If you have local help that you
  223.  want to include (like names of local servers, posting guidelines,
  224.  or whatever), create a HELP member called NNMVSLOC and install it
  225.  in the same library.
  226.  
  227.  11. Copy all the members of the panel PDS into the ISPF panel library
  228.  specified in the NNMVS exec.
  229.  
  230. --------------------------------------------------------------------
  231.  
  232.  Note:  Make sure that the C/370 run time library is available,
  233.  either in the system link list or in the ISPLLIB concatenation,
  234.  before attempting to run NNMVS.
  235.  
  236.  If the C/370 runtime library is not in the link list or otherwise
  237.  available to ISPF at execution time, you may arrange for it to be
  238.  allocated via LIBDEF in the NNMVS exec (I haven't tried this).
  239.  
  240. --------------------------------------------------------------------
  241.  
  242.  Questions?  Comments?  Suggestions?  Gripes?  Requests?  Musings?
  243.  
  244.  You can communicate all of these via the LISTSERV mailing list
  245.  NNMVS-L, maintained at VM.USC.EDU.  To get on this list, send mail to
  246.  LISTSERV@USCVM (or LISTSERV@VM.USC.EDU) with the following line in
  247.  the message body:
  248.  
  249.    SUBSCRIBE NNMVS-L firstname lastname
  250.  
  251.  Please keep in mind that further requests (e.g. to unsubscribe from
  252.  the list) must be sent to the LISTSERV address, *not* to the list.
  253.  The response you'll get from the SUBSCRIBE message will tell you
  254.  about this and more - so be sure to save it.
  255.  
  256. --------------------------------------------------------------------
  257.  
  258.  Please email all other correspondence to...
  259.  
  260.  Steve Bacher      <seb@draper.com> or <seb1525@mvs.draper.com>
  261.  
  262. ./   ADD NAME=$CHANGES,SSI=01050004
  263.  
  264.  New Features in V3
  265.  
  266.   Newsgroup article management is radically different, which should
  267.   result in improvements in response time and memory usage, as well
  268.   as avoiding out-of-memory abends.
  269.  
  270.   A new pseudo-browse interface replaces the BRIF code, enabling
  271.   more commands while browsing a news article.
  272.  
  273.   The PRT command is implemented, similar to EXTRACT except that it
  274.   prints to the SYSOUT class of your choice.
  275.  
  276.   You have the option of letting the cursor remain next to the most
  277.   recently selected newsgroup or article.
  278.  
  279.   New commands to simplify debugging have been added.
  280.  
  281.   Additional installation-time customization for different levels
  282.   of ISPF.
  283.  
  284.   Miscellaneous bug fixes and feature tweaks.
  285.  
  286.  Latest Fixes to V2 R4
  287.  
  288.  NNMCLRNG.C: - Fix memory leak when exiting from NNMVS.
  289.  
  290.  NNMDLANG.C: - Fix 0C4 in "new newsgroups" function when the server
  291.                has duplicate entries in the active.times file.
  292.  
  293.              - Check for bad output from news server's active file
  294.                in the NNTP LIST command, adjust counts and display a
  295.                nasty message so the user can nag the administrator.
  296.  
  297.  NNMBPEXT.C: - Fix bug whereby all article headers were being
  298.                retrieved even when EXTRACT UNREAD was requested
  299.                in a batch job, causing excessive resource usage
  300.                and memory blowouts.
  301.  
  302.  New Features In V2 R4
  303.  
  304.  * Memory usage has been improved significantly.
  305.  
  306.  * Handling of missing/expired articles has been improved.
  307.  
  308.  * Miscellaneous Bug Fixes
  309.  
  310.  * Enhancements to NNMVSP Exec
  311.  
  312.  New Features In V2 R3 M2
  313.  
  314.  * New commands:
  315.  
  316.  - SORT Subject / Number - in article viewing mode, you may use this
  317.    command to sort the article display by subject or return it to the
  318.    default article-number order.  Note that this may require a lot of
  319.    processing, both to retrieve article titles and to perform the
  320.    sorting, which tries to match messages up with "re:" replies.
  321.    When the LOCATE command is issued from an article display in this
  322.    mode, it takes a character string rather than a number.
  323.  
  324.  - QUIT - from almost any panel, terminates NNMVS immediately.
  325.    It works like repeated END's, which means that it will save
  326.    your NEWSRC file.  (QUIT from display-new-newsgroups or
  327.    display-bogus-newsgroups skips updating NEWSRC, though, for
  328.    your protection.)
  329.  
  330.  * Miscellaneous changes:
  331.  
  332.    The MARKALL and UNMARKALL commands now prompt you as to whether
  333.    you want to mark all the articles in the newsgroup or just the
  334.    ones currently shown in the table.
  335.  
  336.  * The extra blank line that used to appear at the bottom of articles
  337.    is gone.  There may be some effects on article extraction,
  338.    particularly when append mode is used, but in general this means
  339.    that what you get is more like what is really out there.
  340.  
  341.  * In POST and MAIL, the format of the inserted message and the
  342.    dashed line separating the signature from the body have been
  343.    changed to be more in accordance with standard practice.
  344.  
  345.  * Even more tweaking of missing article handling.  It's better
  346.    than it was, and may even be considered acceptable now.
  347.  
  348.  * Removed Features
  349.  
  350.    Apologies:  The PATH variable in batch has been removed.
  351.    It was of dubious value (I'm sure you don't miss it).
  352.    Basically, we needed the slot to implement subject sorting.
  353.  
  354.  New Features In V2 R3 M1
  355.  
  356.  * A user option to turn automatic scrolling on or off in the
  357.    newsgroup and article display tables has been added.
  358.  
  359.  * In POST and MAIL, headers are no longer inserted into the text of
  360.    your reply.  Instead, a message of the form
  361.     "In article <messageid> on <date>, <author> writes:"
  362.    is inserted.
  363.  
  364.  * Remaining bugs and pitfalls of missing articles are finally
  365.    cleared up (hopefully).
  366.  
  367.  * The ONLY and FIND commands in article display mode will cause
  368.    fetching of article headers if you are in "A" (all articles) mode.
  369.  
  370.  * An OPTION operand has been added to the NNMVS exec, and support has
  371.    been added to NNMVS so that you will go directly to the requested
  372.    option if you use this and provide a number of other values.
  373.  
  374.  * An attempt to protect users from crashing TCP/IP with multiple
  375.    copies of socket applications is included.
  376.  
  377.  New Features In V2 R3
  378.  
  379.  * New Commands for Controlling Newsgroup and Article Displays
  380.  
  381.    Note: In the following descriptions of operands, "strings" are
  382.    unquoted single words or strings quoted with either single or double
  383.    quotes.  Case is ignored.
  384.  
  385.    The following new commands are available on the newsgroup display:
  386.  
  387.      ORDER {Alphabetic/List} - specify the order in which the groups are
  388.      listed.  The initial setting is A (alphabetic).  You may change to
  389.      L (list) to view the newsgroups in the same order as the NNTP
  390.      server's active file (what the NNTP "LIST" command returns).
  391.  
  392.      ONLY "string" - limit the newsgroup display to newsgroups with
  393.      "string" in the name.  Type ONLY with no operands to restore
  394.      the display to all newsgroups (or registered, depending).
  395.  
  396.      FIND "string" {NEXT/PREV/FIRST/LAST} - position the newsgroup
  397.      display to the next, previous, first or last group which has
  398.      "string" in the name.  FIND with no operands repeats the find.
  399.  
  400.    The following new commands are available on the article display:
  401.  
  402.      ONLY "string" - limit the article display to articles with
  403.      "string" in the subject.  Type ONLY with no operands to restore
  404.      the display to all articles (read or unread, depending).
  405.  
  406.      FIND "string" {NEXT/PREV/FIRST/LAST} - position the article
  407.      display to the next, previous, first or last article which has
  408.      "string" in the subject.  FIND with no operands repeats the find.
  409.  
  410.  * New Options for Navigating Article Views
  411.  
  412.    The following new commands are available from article browse:
  413.  
  414.      NEXTU or NU - like NEXT but goes to the next unread article.
  415.  
  416.      NEXTT or NT - like NEXT but goes to the next article currently in
  417.                    the table.  When you use ONLY to filter the article
  418.                    display, NEXTT honors the filter.  NEXT doesn't.
  419.  
  420.      NEXTS or NS - like NEXT but goes to the next article in the current
  421.                    subject thread.
  422.  
  423.      PREVU(PU), PREVT(PT), PREVS(PS) are analogous to the above.
  424.  
  425.      FIRSTSUBJ or FS - goes to the first article in the current
  426.                        subject thread.
  427.      LASTSUBJ or LS  - goes to the last article in the current
  428.                        subject thread.
  429.      NEWSUBJ or NS   - goes to the first unread article of a subject
  430.                        other than the current thread.
  431.      SUBJECT or SUBJ - displays or changes the current subject.
  432.  
  433.  * Prompting to Protect Existing Data Sets on EXTRACT
  434.  
  435.    When you use the EXTRACT command, if the data set already exists
  436.    you will get a pop-up asking you to confirm that you want to
  437.    reuse the data set.  Simply press ENTER to do so.
  438.  
  439.  * Changes To Commands
  440.  
  441.    The NNTP command may now be specified like this:
  442.  
  443.      NNTP   - by itself, puts you in the NNTP panel, as before
  444.      NNTP nntp-command   - executes NNTP command immediately
  445.  
  446.      For example:  NNTP GROUP COMP.LANG.LISP
  447.                    NNTP HELP
  448.  
  449.    The OPTIONS command has been changed to take you to a menu of
  450.    general options.  The RFC822 header settings are now option 1.
  451.    You can type OPT 1 to go directly there if you don't want to
  452.    see the extra panel.  Also, in BROWSE, you can type HEADERS
  453.    (or HEADER) instead of OPTION to go directly to the RFC822
  454.    header setting panel.
  455.  
  456.    In addition to RFC822 header display options, you may now specify
  457.    how you want screen displays to tell you about operations in process.
  458.    (There are some fancy new ways that NNMVS can do this.)
  459.    You can also control the prompting for overwriting on EXTRACT.
  460.  
  461.  * Changes to Selection Codes
  462.  
  463.    When you select "A" to see all the articles in a newsgroup,
  464.    NNMVS will fill in the title lines.  No more empty lines.
  465.    To save processing, it will get only those that are necessary
  466.    to fill your screen.  Scrolling down (or up) will get the next
  467.    batch - this will appear to be slower.
  468.  
  469.    Also, only those articles that have actually been fetched (not
  470.    just the headers) will be retained in the table when you switch
  471.    back to using "S" to look at the articles in the newsgroup.
  472.  
  473.    Note that whether you select "A" or "S" will affect subject
  474.    searches.  If you selected "S", subject searches will be limited
  475.    to unread or already-retrieved articles.  If you selected "A",
  476.    subject searches will retrieve previously read articles, and
  477.    potentially take longer.
  478.  
  479.    You can select "N" to view only new (unseen) articles.  "N" is
  480.    like "S" except that articles are removed from the display once
  481.    they are read whenever you reenter the article display or change
  482.    the viewing criteria.
  483.  
  484.    The "Z" option, which will remain undocumented for now, is similar
  485.    to the "A" option except that it retrieves NO articles headers,
  486.    read or unread.  Good for quick entry into a huge newsgroup, but
  487.    not very good at recording the correct status of the articles.
  488.  
  489.    You can select "C" to cancel an article by posting a control request
  490.    to the server.  You must be the original author (poster) of the
  491.    article to be allowed to cancel it.  Cancellation is implemented
  492.    by sending a control message to the NNTP server.
  493.  
  494.  * POST, FOLLOWUP and REPLY now allow you to specify a Reply-to email
  495.    address and a signature file.  In addition, you may specify a
  496.    Followup-to list of newsgroups on POST or FOLLOWUP.
  497.  
  498.  * FOLLOWUP and REPLY now follow the RFC1036 rules for generating
  499.    the default lists of newsgroups to post to and mail address to
  500.    reply to.  FOLLOWUP even checks if the Followup-to: header says
  501.    "poster" or contains an email address, and strongly suggests
  502.    that you email instead of posting.  Since BITNET postings dont
  503.    conform to RFC standards, the actual From: address is displayed
  504.    for REPLY in case you need to type it in.
  505.  
  506.  * New Batch mode variable CHECKPOINT allows you to control whether the
  507.    NEWSRC file gets rewritten on every change or just at the end of a
  508.    batch run.  Good for preventing NEWSRC wipeouts on 322 abends.
  509.  
  510.  * Support for Multiple NNMVS's in a Single TSO Session
  511.    (assuming that they're talking to two different servers and
  512.    that you have the required TCP/IP multitasking socket support
  513.    APAR from IBM).
  514.  
  515.    Basically, it dynamically generates a ddname for the newsrc file,
  516.    and you can specify different newsrc files, so there you go.
  517.  
  518.    Warning:  PIE users - DO NOT run 2 NNMVS's from different PIE
  519.    sessions - the IBM TCP/IP fix doesn't work for this!  Use ISPF
  520.    split screen to do it.
  521.  
  522.  * Optional Driver CLIST and REXX exec using XPROC to specify
  523.    parameters in CLIST-style Syntax
  524.  
  525.    See installation instructions for details.
  526.  
  527. ./   ADD NAME=$MISC,SSI=01030003
  528.  
  529. Miscellaneous Notes and Gotchas
  530.  
  531. ========================================================================
  532.  
  533.  * C/370 Kanji Feature
  534.  
  535.  If your C/370 was not installed properly (e.g. you assumed that CBIPO
  536.  would take care of everything - you wretched fool!), it is possible
  537.  that you have the wrong national language for messages.  This will
  538.  become apparent as soon as you fail to open a file, since the C/370
  539.  perror() function will write gibberish to stderr.  To fix this, bug
  540.  your MVS systems programmer to reinstall C/370, e.g. with JDL1214
  541.  and without JCLB212 (for V2R1).  It may be more complicated than that.
  542.  
  543. ========================================================================
  544.  
  545.  * C/370 Attention Handling
  546.  
  547. C/370 doesn't handle PA1 (attention) interrupts properly - in fact,
  548. it completely screws them up, so you end up in an unbreakable loop
  549. when you try to break out of a C/370 application running under ISPF
  550. that uses the TCP/IP socket library.
  551.  
  552. As a temporary circumvention, you should apply a zap to module IBMBLIIA
  553. in your run-time load library.  The zap for C/370 V2R1, for example,
  554. looks like this:
  555.  
  556.    NAME IBMBLIIA IBMBLII1
  557.    VER 2250 0A60
  558.    REP 2250 1BFF
  559.  
  560.   I.E., find the SVC 96 (STAX) instruction and NOP it.
  561.  
  562.   Go ahead and apply it (preferably to a copy of IBMBLIIA in a user
  563.   library from which you run your favorite C/370 application, like
  564.   NNMVS, for example).  Now you can feel free to do anything you like,
  565.   because you can always attention out.
  566.  
  567.   If you find that you need this zap, please make sure that IBM hears
  568.   from you about the problem.   The more customers they hear from, the
  569.   more likely it is that something will be done to fix it.
  570.  
  571.   Be aware that this turns off attention handling entirely - but this
  572.   has turned out to be the only desirable behavior.  Note that SIGINT
  573.   handling has never worked in C/370.  If you don't believe this, then
  574.   just compile and run the sample program in member SIGFAIL.
  575.  
  576. ./   ADD NAME=ALLOAD,SSI=01040000
  577. //JOBNAME  JOB ACCOUNT,'NAME'
  578. //*                                                                  */
  579. //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  580. //*                                                                  */
  581. //* This software is provided on an "AS IS" basis.  All warranties,  */
  582. //* including the implied warranties of merchantability and fitness, */
  583. //* are expressly denied.                                            */
  584. //*                                                                  */
  585. //* Provided this copyright notice is included, this software may    */
  586. //* be freely distributed and not offered for sale.                  */
  587. //*                                                                  */
  588. //* Changes or modifications may be made and used only by the maker  */
  589. //* of same, and not further distributed.  Such modifications should */
  590. //* be mailed to the author for consideration for addition to the    */
  591. //* software and incorporation in subsequent releases.               */
  592. //*                                                                  */
  593. //*
  594. //* Allocate NNMVS load library before install
  595. //*
  596. //NNALLOC PROC BS='6233',U='3380',V='',
  597. //             PRI='100',SEC='100',DIR='35'
  598. //*
  599. //IEFBR14  EXEC PGM=IEFBR14
  600. //ALLOCDD  DD   DISP=(NEW,CATLG,DELETE),DSN=&LIB,
  601. //         DCB=(RECFM=U,BLKSIZE=&BS),
  602. //         SPACE=(&BS,(&PRI,&SEC,&DIR)),UNIT=&U,VOL=SER=&V
  603. //*
  604. //         PEND
  605. //*
  606. //* The following step allocates the load library from which the
  607. //* executable program will be run.  If you intend to place the
  608. //* executable into an existing library, you can skip this step.
  609. //* Otherwise, the name must match the name used on the LOADLIB
  610. //* parameter of the NNLINK procedure in the COMPILE JCL.
  611. //*
  612. //ALLOC1   EXEC NNALLOC,PRI=50,SEC=50,DIR=35,
  613. //         LIB='NNMVS.LOAD'
  614. //*
  615. ./   ADD NAME=AUTH,SSI=01000039
  616. #
  617. # This file is used by NNTP clients (NNMVS) on this system to connect
  618. # to news servers that require authentication, according to the new
  619. # NNTO authorization protocol.  It is ignored if the news server does
  620. # not support this protocol.  If the news server supports it, the user
  621. # must be defined in the server host's /etc/passwd file and its uid
  622. # must be the same as the uid of the user "nntp" - otherwise the server
  623. # will disconnect the client.
  624. #
  625. # A server given here without a user or password will be accepted
  626. # by NNMVS without an attempt to gain the server's authorization.
  627. #
  628. # serverhost  user  password
  629. #
  630.   AUTHHOST    NNTP  JOSHUA
  631.   NOAUTHHOST
  632. ./   ADD NAME=COMPILE
  633. //JOBNAME  JOB ACCOUNT,'NAME'
  634. //*                                                                  */
  635. //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  636. //*                                                                  */
  637. //* This software is provided on an "AS IS" basis.  All warranties,  */
  638. //* including the implied warranties of merchantability and fitness, */
  639. //* are expressly denied.                                            */
  640. //*                                                                  */
  641. //* Provided this copyright notice is included, this software may    */
  642. //* be freely distributed and not offered for sale.                  */
  643. //*                                                                  */
  644. //* Changes or modifications may be made and used only by the maker  */
  645. //* of same, and not further distributed.  Such modifications should */
  646. //* be mailed to the author for consideration for addition to the    */
  647. //* software and incorporation in subsequent releases.               */
  648. //*                                                                  */
  649. //*********************************************************************
  650. //*
  651. //* Compile some or all NNMVS C/370 sources to make the SYSLIN input
  652. //* to the linkedit of the executable NNMMAIN load module.
  653. //*
  654. //NNCCL  PROC MEMBER=,
  655. //            SRCLIB='NNMVS.C',                  NNMVS C source PDS
  656. //            HDRLIB='NNMVS.H',                  NNMVS C headers PDS
  657. //            COMMHDR='TCPIP.COMMMAC',           C/370 TCP/IP headers
  658. //            C370HDR='SYS1.EDCHDRS',            C/370 standard headers
  659. //            SYSMSGS='SYS1.EDCMSGS',            C/370 messages file
  660. //            SYSMSGM='EDCMSGE',                 C/370 message member
  661. //            VIOUNIT=VIO,                       Temporary disk unit
  662. //            OUTCLAS='*',                          SYSOUT class
  663. //            CPARMS='SOURCE EXPMAC NOAGGR NOXREF', Compile parameters
  664. //            TEST=TEST                             TEST or NOTEST
  665. //*
  666. //CCOMP     EXEC PGM=EDCCOMP,PARM='MARGINS(1,72) &TEST &CPARMS'
  667. //SYSMSGS   DD DISP=SHR,DSN=&SYSMSGS(&SYSMSGM)
  668. //SYSIN     DD DISP=SHR,DSN=&SRCLIB(&MEMBER)
  669. //SYSLIB    DD DISP=SHR,DSN=&COMMHDR
  670. //          DD DISP=SHR,DSN=&C370HDR
  671. //USERLIB   DD DISP=SHR,DSN=&HDRLIB
  672. //SYSLIN    DD DSN=&&LOADSET,UNIT=&VIOUNIT,DISP=(MOD,PASS),
  673. //   SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200)
  674. //SYSPRINT  DD SYSOUT=&OUTCLAS
  675. //SYSCPRT   DD SYSOUT=&OUTCLAS
  676. //SYSUT1    DD DSN=&&SYSUT1,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  677. //   SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200)
  678. //SYSUT4    DD DSN=&&SYSUT4,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  679. //   SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=80,BLKSIZE=3200)
  680. //SYSUT6    DD DSN=&&SYSUT6,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  681. //   SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
  682. //SYSUT7    DD DSN=&&SYSUT7,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  683. //   SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
  684. //SYSUT8    DD DSN=&&SYSUT8,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  685. //   SPACE=(32000,(30,30)),DCB=(RECFM=FB,LRECL=3200,BLKSIZE=12800)
  686. //SYSUT9    DD DSN=&&SYSUT9,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  687. //   SPACE=(32000,(30,30)),DCB=(RECFM=VB,LRECL=137,BLKSIZE=882)
  688. //SYSUT10   DD SYSOUT=&OUTCLAS
  689. //*
  690. //         PEND
  691. //*
  692. //*********************************************************************
  693. //*
  694. //* Linkedit the executable NNMMAIN load module.
  695. //*
  696. //* Note: If C/370 V1R2 or higher, and you have therefore accepted
  697. //*       the "#define FETCH" in the NN header, you may delete
  698. //*       the line that includes the ISPLINK library.
  699. //*
  700. //* Note: If TCP/IP V2 or higher, remove the PASCAL link libraries
  701. //*       from the JCL and the AMPZMVSB card from the control deck.
  702. //*
  703. //NNLINK PROC LOADLIB='NNMVS.LOAD',              Executable load library
  704. //            PLIBASE='SYS1.PLIBASE',            PL/1   link library
  705. //            EDCBASE='SYS1.SEDCBASE',           C/370  link library
  706. //            IBMBASE='SYS1.SIBMBASE',           PL/1+C common library
  707. //            COMMTXT='TCPIP.COMMTXT',           TCP/IP link library
  708. //            PASRUN3='SYS1.PAS.SAMPRUN3',       PASCAL link library
  709. //            PASRUN1='SYS1.PAS.SAMPRUN1',       PASCAL link library
  710. //            PASMSG1='SYS1.PAS.SAMPMSG1',       PASCAL link library
  711. //            ISPLINK='ISP.V3R2M0.ISPLLIB',      ISPLINK link library
  712. //            VIOUNIT=VIO,                       Temporary disk unit
  713. //            OUTCLAS='*',                          SYSOUT class
  714. //            LPARMS='LIST,LET,MAP',                Linkedit parameters
  715. //            TEST=TEST                             TEST or NOTEST
  716. //*
  717. //LKED      EXEC PGM=IEWL,PARM='AMODE(31),&TEST,&LPARMS'
  718. //SYSPRINT  DD SYSOUT=&OUTCLAS
  719. //SYSLIB    DD DISP=SHR,DSN=&PLIBASE
  720. //          DD DISP=SHR,DSN=&EDCBASE
  721. //          DD DISP=SHR,DSN=&IBMBASE
  722. //          DD DISP=SHR,DSN=&COMMTXT
  723. //          DD DISP=SHR,DSN=&PASRUN3  if TCP/IP V1 only
  724. //          DD DISP=SHR,DSN=&PASRUN1  if TCP/IP V1 only
  725. //          DD DISP=SHR,DSN=&PASMSG1  if TCP/IP V1 only
  726. //          DD DISP=SHR,DSN=&ISPLINK  if C/370 V1R1 with #undef FETCH
  727. //SYSLMOD   DD DISP=SHR,DSN=&LOADLIB
  728. //SYSUT1    DD DSN=&&SYSUT1,UNIT=&VIOUNIT,DISP=(NEW,DELETE),
  729. //          SPACE=(32000,(30,30))
  730. //*
  731. //         PEND
  732. //*
  733. //NNMADDNG EXEC NNCCL,MEMBER=NNMADDNG
  734. //NNMADJUA EXEC NNCCL,MEMBER=NNMADJUA
  735. //NNMALLAV EXEC NNCCL,MEMBER=NNMALLAV
  736. //NNMALLOC EXEC NNCCL,MEMBER=NNMALLOC
  737. //NNMAUTH  EXEC NNCCL,MEMBER=NNMAUTH
  738. //NNMBATCH EXEC NNCCL,MEMBER=NNMBATCH
  739. //NNMBBEXP EXEC NNCCL,MEMBER=NNMBBEXP
  740. //NNMBCONN EXEC NNCCL,MEMBER=NNMBCONN
  741. //NNMBDECL EXEC NNCCL,MEMBER=NNMBDECL
  742. //NNMBFLUS EXEC NNCCL,MEMBER=NNMBFLUS
  743. //NNMBGCMD EXEC NNCCL,MEMBER=NNMBGCMD
  744. //NNMBGDO  EXEC NNCCL,MEMBER=NNMBGDO
  745. //NNMBGEXP EXEC NNCCL,MEMBER=NNMBGEXP
  746. //NNMBGTOK EXEC NNCCL,MEMBER=NNMBGTOK
  747. //NNMBPDEC EXEC NNCCL,MEMBER=NNMBPDEC
  748. //NNMBPDER EXEC NNCCL,MEMBER=NNMBPDER
  749. //NNMBPELS EXEC NNCCL,MEMBER=NNMBPELS
  750. //NNMBPEXE EXEC NNCCL,MEMBER=NNMBPEXE
  751. //NNMBPEXT EXEC NNCCL,MEMBER=NNMBPEXT
  752. //NNMBPFOR EXEC NNCCL,MEMBER=NNMBPFOR
  753. //NNMBPHEL EXEC NNCCL,MEMBER=NNMBPHEL
  754. //NNMBPIF  EXEC NNCCL,MEMBER=NNMBPIF
  755. //NNMBPLIS EXEC NNCCL,MEMBER=NNMBPLIS
  756. //NNMBPMAR EXEC NNCCL,MEMBER=NNMBPMAR
  757. //NNMBPNNT EXEC NNCCL,MEMBER=NNMBPNNT
  758. //NNMBPPUT EXEC NNCCL,MEMBER=NNMBPPUT
  759. //NNMBPQUE EXEC NNCCL,MEMBER=NNMBPQUE
  760. //NNMBPQUI EXEC NNCCL,MEMBER=NNMBPQUI
  761. //NNMBPREG EXEC NNCCL,MEMBER=NNMBPREG
  762. //NNMBPSET EXEC NNCCL,MEMBER=NNMBPSET
  763. //NNMBPVAR EXEC NNCCL,MEMBER=NNMBPVAR
  764. //NNMBSOUT EXEC NNCCL,MEMBER=NNMBSOUT
  765. //NNMBSYNT EXEC NNCCL,MEMBER=NNMBSYNT
  766. //NNMBTEXT EXEC NNCCL,MEMBER=NNMBTEXT
  767. //NNMBTRAS EXEC NNCCL,MEMBER=NNMBTRAS
  768. //NNMBVGET EXEC NNCCL,MEMBER=NNMBVGET
  769. //NNMBVPUT EXEC NNCCL,MEMBER=NNMBVPUT
  770. //NNMBXFAR EXEC NNCCL,MEMBER=NNMBXFAR
  771. //NNMBXFNG EXEC NNCCL,MEMBER=NNMBXFNG
  772. //NNMCAR   EXEC NNCCL,MEMBER=NNMCAR
  773. //NNMCLRNG EXEC NNCCL,MEMBER=NNMCLRNG
  774. //NNMCLRTX EXEC NNCCL,MEMBER=NNMCLRTX
  775. //NNMCNRF  EXEC NNCCL,MEMBER=NNMCNRF
  776. //NNMCONN  EXEC NNCCL,MEMBER=NNMCONN
  777. //NNMCOPY  EXEC NNCCL,MEMBER=NNMCOPY
  778. //NNMDCAN  EXEC NNCCL,MEMBER=NNMDCAN
  779. //NNMDFAIL EXEC NNCCL,MEMBER=NNMDFAIL
  780. //NNMDISC  EXEC NNCCL,MEMBER=NNMDISC
  781. //NNMDISPL EXEC NNCCL,MEMBER=NNMDISPL
  782. //NNMDLANG EXEC NNCCL,MEMBER=NNMDLANG
  783. //NNMDMAIL EXEC NNCCL,MEMBER=NNMDMAIL
  784. //NNMDMENU EXEC NNCCL,MEMBER=NNMDMENU
  785. //NNMDNG   EXEC NNCCL,MEMBER=NNMDNG
  786. //NNMDNNTP EXEC NNCCL,MEMBER=NNMDNNTP
  787. //NNMDOIT  EXEC NNCCL,MEMBER=NNMDOIT
  788. //NNMDPOST EXEC NNCCL,MEMBER=NNMDPOST
  789. //NNMDSOPT EXEC NNCCL,MEMBER=NNMDSOPT
  790. //NNMDUMP  EXEC NNCCL,MEMBER=NNMDUMP
  791. //NNMESRVR EXEC NNCCL,MEMBER=NNMESRVR
  792. //NNMESTNG EXEC NNCCL,MEMBER=NNMESTNG
  793. //NNMFREEM EXEC NNCCL,MEMBER=NNMFREEM
  794. //NNMGETDS EXEC NNCCL,MEMBER=NNMGETDS
  795. //NNMGETM  EXEC NNCCL,MEMBER=NNMGETM
  796. //NNMGSRVL EXEC NNCCL,MEMBER=NNMGSRVL
  797. //NNMIERR  EXEC NNCCL,MEMBER=NNMIERR
  798. //NNMIGET  EXEC NNCCL,MEMBER=NNMIGET
  799. //NNMINIT  EXEC NNCCL,MEMBER=NNMINIT
  800. //NNMISPF  EXEC NNCCL,MEMBER=NNMISPF
  801. //NNMIVGET EXEC NNCCL,MEMBER=NNMIVGET
  802. //NNMIVPUT EXEC NNCCL,MEMBER=NNMIVPUT
  803. //NNMMAIN  EXEC NNCCL,MEMBER=NNMMAIN
  804. //NNMMARR  EXEC NNCCL,MEMBER=NNMMARR
  805. //NNMMARU  EXEC NNCCL,MEMBER=NNMMARU
  806. //NNMNNTP  EXEC NNCCL,MEMBER=NNMNNTP
  807. //NNMONRF  EXEC NNCCL,MEMBER=NNMONRF
  808. //NNMOUTTX EXEC NNCCL,MEMBER=NNMOUTTX
  809. //NNMPICK  EXEC NNCCL,MEMBER=NNMPICK
  810. //NNMPMSG  EXEC NNCCL,MEMBER=NNMPMSG
  811. //NNMPNG   EXEC NNCCL,MEMBER=NNMPNG
  812. //NNMQAR   EXEC NNCCL,MEMBER=NNMQAR
  813. //NNMQNG   EXEC NNCCL,MEMBER=NNMQNG
  814. //NNMRARH  EXEC NNCCL,MEMBER=NNMRARH
  815. //NNMRART  EXEC NNCCL,MEMBER=NNMRART
  816. //NNMRBFM  EXEC NNCCL,MEMBER=NNMRBFM
  817. //NNMRECON EXEC NNCCL,MEMBER=NNMRECON
  818. //NNMRPERR EXEC NNCCL,MEMBER=NNMRPERR
  819. //NNMSAVE  EXEC NNCCL,MEMBER=NNMSAVE
  820. //NNMSOCKT EXEC NNCCL,MEMBER=NNMSOCKT
  821. //NNMSOPT  EXEC NNCCL,MEMBER=NNMSOPT
  822. //NNMSORT  EXEC NNCCL,MEMBER=NNMSORT
  823. //NNMSSRVR EXEC NNCCL,MEMBER=NNMSSRVR
  824. //NNMSTRLC EXEC NNCCL,MEMBER=NNMSTRLC
  825. //NNMSUMAT EXEC NNCCL,MEMBER=NNMSUMAT
  826. //NNMTSO   EXEC NNCCL,MEMBER=NNMTSO
  827. //NNMUNALC EXEC NNCCL,MEMBER=NNMUNALC
  828. //NNMUPDT  EXEC NNCCL,MEMBER=NNMUPDT
  829. //NNMVAR   EXEC NNCCL,MEMBER=NNMVAR
  830. //NNMVIEW  EXEC NNCCL,MEMBER=NNMVIEW
  831. //NNMVNG   EXEC NNCCL,MEMBER=NNMVNG
  832. //NNMVTX   EXEC NNCCL,MEMBER=NNMVTX
  833. //NNMXARTT EXEC NNCCL,MEMBER=NNMXARTT
  834. //NNMXARTX EXEC NNCCL,MEMBER=NNMXARTX
  835. //NNMXLIST EXEC NNCCL,MEMBER=NNMXLIST
  836. //NNMXTX   EXEC NNCCL,MEMBER=NNMXTX
  837. //*
  838. //* Link NNMVS load module.  Like SMP/E, expect return code 8 when
  839. //* doing this from scratch.  Additional one-or-two-module links
  840. //* will just replace the corresponding parts of the load module.
  841. //*
  842. //NNLINK EXEC NNLINK
  843. //LKED.SYSLIN DD DISP=(OLD,DELETE),DSN=&&LOADSET
  844. //            DD *
  845.  INCLUDE SYSLMOD(NNMMAIN)             if included first time, RC = 8
  846.  INCLUDE SYSLIB(AMPZMVSB)             include if TCP/IP V1 only
  847.  ENTRY   CEESTART
  848.  NAME    NNMMAIN(R)
  849. /*
  850. ./   ADD NAME=GRAMMAR,SSI=01030032
  851.  
  852.         Grammar for NNMVS batch mode expressions.
  853.  
  854. /*-------------------------------------------------------------------*/
  855.  
  856. exp         :       choice
  857.             :       "IF" exp "THEN" exp "ELSE" exp
  858.                                        /* IF flag THEN any ELSE any */
  859.  
  860. choice      :       relation
  861.             :       choice logop relation   /* flag | flag -> flag  */
  862.  
  863. relation    :       value
  864.             :       value relop value       /* any > any   -> flag  */
  865.  
  866. value       :       quantity
  867.             :       quantity quantity       /* any any    -> string */
  868.  
  869. quantity    :       term
  870.             :       quantity addop term     /* num + num  -> number */
  871.  
  872. term        :       factor
  873.             :       term mulop factor       /* num * num -> number  */
  874.  
  875. factor      :       constant
  876.             :       variable                /* FOO, if declared     */
  877.             :       unop factor             /* - number  -> number  */
  878.             :       "(" exp ")"             /* (a + b * c > d | e ) */
  879.  
  880. constant    :       number
  881.             :       string
  882.             :       flag
  883.  
  884. unop        :       "+"
  885.             :       "-"
  886.             :       "!"
  887.             :       "^"
  888.  
  889. addop       :       "+"
  890.             :       "-"
  891.  
  892. mulop       :       "*"
  893.             :       "/"
  894.  
  895. logop       :       "&"
  896.             :       "|"
  897.  
  898.  
  899. relop       :       "="
  900.             :       ">"
  901.             :       "<"
  902.             :       "=="
  903.             :       ">="
  904.             :       "<="
  905.             :       "!="
  906.             :       "!>"
  907.             :       "!<"
  908.             :       "^="
  909.             :       "^>"
  910.             :       "^<"
  911.             :       "IN"
  912.  
  913. variable    :       [a-z]*
  914.  
  915. number      :       [0-9]*
  916.  
  917. string      :       ""...""
  918.  
  919. flag        :       "TRUE"
  920.             :       "FALSE"
  921.             :       "ON"
  922.             :       "OFF"
  923.             :       "YES"
  924.             :       "NO"
  925. ./   ADD NAME=HELP,SSI=010E0023
  926.                     NNMVS Batch Mode Help
  927.  
  928.  The following commands are available:
  929.  
  930.  Top-Level Commands (in top-level mode, picking newsgroups)
  931.  
  932.    FOR ALL | REGISTERED | UNREGISTERED {WHEN filter} commandlist;
  933.  
  934.       where filter is any flag expression, evaluated per newsgroup,
  935.       and commandlist is a single command or DO; commands; END;
  936.       and the commands are per-newsgroup commands.
  937.  
  938.  Per-Newsgroup Commands (in newsgroup mode, picking articles)
  939.  
  940.    REGISTER
  941.    DEREGISTER
  942.    EXTRACT ALL | READ | UNREAD
  943.    QUERY 
  944.    FOR ALL | READ | UNREAD | num {TO num} {WHEN filter} commandlist
  945.  
  946.       where filter is any flag expression, evaluated per article,
  947.       and commandlist is a single command or DO; commands; END
  948.       and the commands are per-article commands.
  949.  
  950.  Per-Article Commands (in article mode)
  951.  
  952.    MARK {READ | UNREAD}
  953.    LIST
  954.    EXTRACT
  955.    QUERY 
  956.  
  957.  Miscellaneous Commands
  958.  
  959.    IF condition THEN commandlist; {ELSE commandlist;}
  960.  
  961.       where condition is any flag expression,
  962.       and commandlist is a single command or DO; commands; END;
  963.       and the commands are of the same mode as the one in which
  964.       the IF occurs.
  965.  
  966.    PUT stringexpression               # writes to output file
  967.    EXEC stringexpression              # executes system command
  968.    NNTP stringexpression              # transmits NNTP request
  969.    QUIT                               # terminates NNMVS
  970.    VARS                               # dumps current variables
  971.  
  972.    {SET} variable { = } expression
  973.  
  974.      Variable must be builtin or declared (see DECLARE below)
  975.  
  976.    DECLARE variable {STRING | NUMBER | FLAG}
  977.  
  978.      Note:  DECLARE is the only command which is executed immediately.
  979.             All other commands are parsed and then the entire command
  980.             stream is executed only if no errors were detected.
  981.  
  982.  Built-in Variables
  983.  
  984.  LOCALPATH (string)  - the hosts's local path name
  985.  DATETIME  (string)  - a time stamp
  986.  SERVER    (string)  - the name of the NNTP server host.  Must be set
  987.                        by the user before attempting a connection.
  988.  OUTFILE   (string)  - the name of an alternate output file for the
  989.                        PUT commands and any commands (like NNTP) that
  990.                        write text.  The default setting, "", uses the
  991.                        NNBATOUT DD.  The value may be a data set name
  992.                        (appended to) or in the form DD:ddname.
  993.  SERVERLIST (flag)   - default is TRUE.  Normally NNMVS will ask for
  994.                        the current list of newsgroups from the NNTP
  995.                        server when it begins processing newsgroups.
  996.                        If you want to suppress this and just use the
  997.                        groups named in NEWSRC, set SERVERLIST to FALSE.
  998.                        Note that this may not save time, and in fact
  999.                        may result in more processing, since NNMVS will
  1000.                        issue a GROUP request to each group requested
  1001.                        when it has not issued a LIST request.
  1002.  AUTOREGISTER (flag) - default is FALSE.  If this is set to TRUE,
  1003.                        new newsgroups will automatically be registered
  1004.                        in the NEWSRC file; otherwise they will be added
  1005.                        as unregistered newsgroups.
  1006.  AUTODELETE   (flag) - default is TRUE.  If this is set to TRUE,
  1007.                        bogus newsgroups (groups in the NEWSRC file that
  1008.                        are not known to the server) will be deleted
  1009.                        from the NEWSRC file.  Set this to FALSE to keep
  1010.                        such newsgroups in NEWSRC anyway.
  1011.  ERROR        (flag) - set to TRUE whenever an NNMVS batch command
  1012.                        operation fails.  This is reset by each NNMVS
  1013.                        batch command, so grab it early.
  1014.  EXACTCASE    (flag) - default is FALSE.  When this is FALSE, string
  1015.                        comparisons and tests succeed regardless of upper
  1016.                        or lower case.  When this is set to TRUE, string
  1017.                        comparisons and tests succeed only if the strings
  1018.                        match exactly.  Thus, "a" = "A" when EXACTCASE is
  1019.                        FALSE, but not when EXACTCASE is TRUE.
  1020.  
  1021.  Variables meaningful to the EXTRACT command:
  1022.  
  1023.  TABEXPAND    (flag) - default is TRUE.  Controls whether tab characters
  1024.                        are to be expanded on EXTRACT.  (Note that tabs
  1025.                        are always expanded on PUT and LIST.)
  1026.  APPEND       (flag) - default is TRUE.  Controls how articles are to be
  1027.                        extracted to sequential files by EXTRACT.
  1028.                        If APPEND is set to FALSE, existing sequential
  1029.                        files will be overwritten.  This option is not
  1030.                        applicable to partitioned data sets (PDS's).
  1031.  SEPARATOR  (string) - default is the null string.  If this is set to
  1032.                        a value other than the null string, the value
  1033.                        will be written between articles as a separator
  1034.                        line.  Meaningful only when APPEND is TRUE.
  1035.  BLANKSEP     (flag) - default is FALSE.  If TRUE, a blank line will be
  1036.                        generated before the separator line when it us
  1037.                        written out between articles.  Otherwise the
  1038.                        separator line, if used, will follow the end of
  1039.                        the preceding article immediately.  Meaningful
  1040.                        only when SEPARATOR and APPEND are set.
  1041.  AUTOMARK     (flag) - default is TRUE.  When this is TRUE, the EXTRACT
  1042.                        operation will mark unread articles READ upon
  1043.                        successful extraction.  It has no effect on
  1044.                        read articles or articles that failed extraction.
  1045.                        Set it to FALSE to prevent EXTRACT from marking
  1046.                        extracted articles read.
  1047.  
  1048.  Variables meaningful in per-newsgroup mode and modes below:
  1049.  
  1050.  GROUP      (string) - the name of the current newsgroop.
  1051.  REGISTERED (flag)   - TRUE if newsgroup is registered.
  1052.  NEWGROUP   (flag)   - TRUE if newsgroup is a new group (found by the
  1053.                        server LIST request but not in NEWSRC).
  1054.  NOSUCHGROUP (flag)  - TRUE if the newsgroup is "bogus" (in NEWSRC but
  1055.                        not found by the server LIST request).
  1056.  COUNT      (number) - the total number of articles in the newsgroup.
  1057.  UNREAD     (number) - the total number of new (unread) articles in the
  1058.                        newsgroup since the last time NNMVS used this
  1059.                        NEWSRC file.
  1060.  FIRST      (number) - the number of the first article in the group.
  1061.  LAST       (number) - the number of the last article in the group.
  1062.  
  1063.  Variables meaningful in per-article mode and modes below:
  1064.  
  1065.  NUMBER     (number) - the current article number.
  1066.  READ       (flag)   - TRUE if article has already been read.
  1067.  MISSING    (flag)   - TRUE if article cannot be retrieved from server.
  1068.  SUBJECT    (string) - text of the Subject: header.
  1069.  DATE       (string) - text of the Date: header, with day name removed.
  1070.  FROM       (string) - text of From: header, author of the article.
  1071.  MESSAGEID  (string) - text of the Message-ID: header.
  1072.  
  1073.  Expression Syntax
  1074.  
  1075.  Expressions can be string expressions, number expressions, or
  1076.  flag expressions.  They can contain constants, variables, and
  1077.  arithmetic or logical expressions.  Strings may be concatenated
  1078.  by placing one next to another, e. g. "foo" "bar".
  1079.  
  1080.  String constants are enclosed in double quotes, with the backslash
  1081.  acting as an escape with which to enclose embedded double quotes.
  1082.  
  1083.  Numeric constants are integers only.
  1084.  
  1085.  Flag constants may be represented as TRUE FALSE ON OFF YES NO.
  1086.  
  1087.  Arithmetic operators:  + - * / as well as unary + and -
  1088.  Logical    operators:  & |     as well as unary !
  1089.  Relational operators:  = != > < >= <= !> !<
  1090.  (Note: == is an alias for =, and ^ may be used wherever ! is.)
  1091.  
  1092.  For strings, the additional relational operator IN is available, e.g.
  1093.  
  1094.    "foo" IN SUBJECT
  1095.  
  1096.  The notation (IF expression THEN expression ELSE expression) is
  1097.  allowed within expressions.
  1098.  
  1099.  The following synonyms are accepted:
  1100.  
  1101.    AND OR NOT EQ NE GT LT GE LE NG NL
  1102.  
  1103.  The character # marks the beginning of a comment.
  1104.  
  1105. Extracting Files
  1106.  
  1107.  EXTRACT writes the contents of one or more news articles out to a file
  1108.  whose name is determined from a table allocated to DDname NNEXTTAB.
  1109.  
  1110.  The format of the extract table is one line per newsgroup as follows:
  1111.  
  1112.   groupname filename
  1113.  
  1114.  where filename is a FULLY QUALIFIED name (quotes ignored) of one of
  1115.  the following formats:
  1116.  
  1117.   sequential data set name
  1118.   wildcarded sequential data set name
  1119.   wildcarded partitioned data set name
  1120.  
  1121.  "Wildcarded" means that there is an asterisk "*" in a strategic
  1122.  position in the file name.  It must be preceded by at least one
  1123.  alphanumeric character and may not be followed by one.
  1124.  
  1125.  When the extraction is done, the asterisk is replaced with the number
  1126.  of the article, zero padded on the left to fill out that segment of
  1127.  the name.
  1128.  
  1129.  Examples:
  1130.  
  1131.   comp.group.one   MYID.COMP.GROUP.SEQ.FOO*
  1132.   comp.group.two   MYID.COMP.GROUP.SEQ.ALL
  1133.   comp.group.three MYID.COMP.GROUP.THREE.PDS(X*)
  1134.   comp.group.four  MYID.COMP.GROUP.NUMBER*.PDS(ANYMEM)
  1135.  
  1136.  So...
  1137.  
  1138.   comp.windows.x  SEB1525.COMP.WINDOWS.X.TEXT.#*
  1139.  
  1140.  defines a series of sequential data sets
  1141.  COMP.WINDOWS.X.TEXT.#0000001
  1142.  COMP.WINDOWS.X.TEXT.#0000002
  1143.  
  1144.  etc.
  1145.  
  1146.  PDS members can be expressed this way:
  1147.  
  1148.   comp.os.vms     COMP.OS.VMS.PDS(VMS*)
  1149.  
  1150.  which gives
  1151.  
  1152.   COMP.OS.VMS.PDS(VMS00001)
  1153.   COMP.OS.VMS.PDS(VMS00002)
  1154.  
  1155.  etc.  If the article number takes more digits, it steals some
  1156.  character positions away from the characters immediately preceding
  1157.  the asterisk.  For example, using the above model:
  1158.  
  1159.   COMP.OS.VMS.PDS(VM142857)
  1160.  
  1161.  The file need not already exist.  If it does not, NNMVS will attempt
  1162.  to guess the appropriate size when it allocates it, as the EXTRACT
  1163.  command does in foreground.
  1164.  
  1165. ./   ADD NAME=NNMVS,SSI=01030000
  1166. //*                                                                  */
  1167. //* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  1168. //*                                                                  */
  1169. //* This software is provided on an "AS IS" basis.  All warranties,  */
  1170. //* including the implied warranties of merchantability and fitness, */
  1171. //* are expressly denied.                                            */
  1172. //*                                                                  */
  1173. //* Provided this copyright notice is included, this software may    */
  1174. //* be freely distributed and not offered for sale.                  */
  1175. //*                                                                  */
  1176. //* Changes or modifications may be made and used only by the maker  */
  1177. //* of same, and not further distributed.  Such modifications should */
  1178. //* be mailed to the author for consideration for addition to the    */
  1179. //* software and incorporation in subsequent releases.               */
  1180. //*                                                                  */
  1181. //NNMVS    PROC DEBUG=,                 say DEBUG=D for debugging
  1182. //             LOADLIB='NNMVS.LOAD',    must match LOADLIB in LINK job
  1183. //             HELP='NNMVS.HELP',              for batch HELP command
  1184. //             NEWSRC='USERID.BATCH.NEWSRC',   separate NEWSRC file
  1185. //             EXTTAB='USERID.NNMVS.EXTTAB'    table used by EXTRACT
  1186. //*
  1187. //* NNMVS batch mode.
  1188. //*
  1189. //NN       EXEC PGM=NNMMAIN,PARM='-B&DEBUG'
  1190. //STEPLIB  DD   DISP=SHR,DSN=&LOADLIB
  1191. //NNNEWSRC DD   DISP=OLD,DSN=&NEWSRC
  1192. //NNEXTTAB DD   DISP=SHR,DSN=&EXTTAB
  1193. //NNBATHLP DD   DISP=SHR,DSN=&HELP
  1194. //SYSPRINT DD   SYSOUT=*
  1195. //SYSERR   DD   SYSOUT=*
  1196. //NNBATOUT DD   SYSOUT=*,DCB=(RECFM=VB,LRECL=255)
  1197. //NNDEBUG  DD   SYSOUT=*
  1198. //NNBATIN  DD   DDNAME=SYSIN
  1199. //*
  1200. //         PEND NNMVS
  1201. ./   ADD NAME=NNMVSHLP,SSI=01020018
  1202. )F Function -
  1203.  
  1204.  NNMVS is a newsreader for reading and posting articles in USENET
  1205.  newsgroups.
  1206.  
  1207.  NNMVS is an NNTP (network news transfer protocol) client that accesses
  1208.  USENET news from a host machine elsewhere on your network that is
  1209.  running an NNTP news server, and displays the news via ISPF.  You must
  1210.  tell NNMVS where this news server is; it does not know otherwise.
  1211.  
  1212.  NNMVS remembers which articles you have read in a "newsrc" data set.
  1213.  You specify the name of this data set on the primary menu, along
  1214.  with the name of the news server host.  Note that both of these
  1215.  are given useful defaults when you start up NNMVS.
  1216.  
  1217.  If you have never used NNMVS before, you use the blank or L option to
  1218.  build up your NEWSRC file from a list retrieved from the server.
  1219.  Then, to limit the list to your favorite newsgroups, you can register
  1220.  (subscribe to) the ones you want while viewing the newsgroup list.
  1221.  
  1222.  You can use L or blank all the time to enter NNMVS.  However,
  1223.  once you have used and built a NEWSRC file, you may wish to use a
  1224.  different entry option to reduce startup time.
  1225.  You can avoid retrieving the whole list by using the R option
  1226.  to view only registered (subscribed) newsgroups, or the A option to
  1227.  view all newsgroups listed in your NEWSRC file.
  1228.  
  1229.  The disadvantage to using A or R is that you do not get the latest
  1230.  additions to the news system when the newsgroup list shows up.
  1231.  But there are ways to get around this.  For example, you can use the
  1232.  N option to get a list of newsgroups added since the last time you
  1233.  retrieved the newsgroup list (i.e. used L or N).
  1234.  
  1235.  If you want to go to a particular newsgroup directly, you can do so
  1236.  via the G option.  When you use this, you must provide the name of
  1237.  the desired newsgroup.
  1238.  
  1239. )I NNMVSLOC          - local NNMVS help goes in member NNMVSLOC
  1240.  
  1241. )X Syntax -
  1242.  
  1243.    %NNMVS
  1244.               SERVER('news server host')
  1245.               GROUP('newsgroup name')
  1246.               NEWSRC('data set name')
  1247.               OPTION(A/G/L/N/O/P/R/X)
  1248.               REGISTERSTATUS(Yes/No/Prompt)
  1249.               FORCE
  1250.               DEBUG
  1251.               TEST
  1252.               BATCH
  1253.               BATCHIN('batch input file name')
  1254.               BATCHOUT('batch output file name')
  1255.               NEW
  1256.               OLD
  1257.  
  1258.    Required:  none
  1259.  
  1260.    Defaults:  User is prompted (via ISPF panel) for all omitted values
  1261.  
  1262.    Notes:     If OPTION is given, then direct entry into the news
  1263.               reader occurs, without display of the NNMVS primary menu.
  1264.               However, if so, then SERVER and NEWSRC are required, and
  1265.               GROUP is also required if OPTION(G) is specified.
  1266.  
  1267.               If BATCH is given, then NEWSRC is required.
  1268.  
  1269. )O Operands -
  1270.  
  1271. ))SERVER('news server host')
  1272.  
  1273.               The hostname of the machine running the news server.
  1274.               Note that an IP address may be specified, but this
  1275.               is obviously not recommended.
  1276.  
  1277.               If an asterisk "*" is specified as the server name,
  1278.               an experimental dialog is invoked which displays an
  1279.               ISPF table of news servers with associated NEWSRC
  1280.               data set names.  You select the news server you want
  1281.               (or add a line associating that server with a specific
  1282.               NEWSRC file).  This feature is courtesy of Leonard Woren
  1283.               (LDW@MVSA.USC.EDU, SHARE installation code USC).
  1284.  
  1285. ))GROUP('newsgroup name')
  1286.  
  1287.               The name of a specific newsgroup you want to see,
  1288.               rather than the list of all newsgroups.  If you specify
  1289.               this, it will merely fill in the corresponding field of
  1290.               the NNMVS primary menu, unless you also specify the
  1291.               keyword OPTION(G) and values for SERVER and NEWSRC.
  1292.  
  1293. ))NEWSRC('data set name')
  1294.  
  1295.               The name of your "newsrc" file, a sequential data set
  1296.               which keeps track of which articles you've already read
  1297.               in which newsgroups.  If this data set does not exist,
  1298.               NNMVS will create it.
  1299.  
  1300.               It is a good idea to use the same NEWSRC file all the
  1301.               time for one news server, but to use separate NEWSRC
  1302.               files for different news servers (should there be any).
  1303.  
  1304.               If you specify this, it will merely fill in the
  1305.               corresponding field of the NNMVS primary menu, unless
  1306.               you also specify values for SERVER and OPTION.
  1307.  
  1308.               If an asterisk "*" is specified as the NEWSRC name,
  1309.               an experimental dialog is invoked which displays an
  1310.               ISPF table of news servers with associated NEWSRC
  1311.               data set names.  You select the news server you want
  1312.               (or add a line associating that server with a specific
  1313.               NEWSRC file).  This feature is courtesy of Leonard Woren
  1314.               (LDW@MVSA.USC.EDU, SHARE installation code USC).
  1315.  
  1316. ))OPTION(A/G/L/N/O/P/R/X)
  1317.  
  1318.               The initial option to start up NNMVS without seeing
  1319.               the primary menu, where the meanings of the letters
  1320.               are those as displayed on the menu:
  1321.  
  1322.               L - List all newsgroups from server
  1323.               N - List new newsgroups from server since last N or L
  1324.               A - Show items from all newsgroups listed in NEWSRC file
  1325.               R - Show items from registered newsgroups in NEWSRC file
  1326.               G - Go directly to the newsgroup named by operand GROUP
  1327.               P - Enter native NNTP protocol commands
  1328.               O - Specify NNMVS options defaults
  1329.               X - Exit NNMVS
  1330.  
  1331.               If you specify this, you must also specify values for
  1332.               SERVER and NEWSRC.  Also, if you specify OPTION(G), you
  1333.               must provide a value for the GROUP keyword.
  1334.  
  1335. ))REGISTERSTATUS(Yes/No/Prompt)
  1336.  
  1337.               When you specify OPTION(R), NNMVS decides whether to
  1338.               get the current status of each registered newsgroup,
  1339.               since it doesn't get that information for free as it
  1340.               does when you use the "L" (list) option.  Therefore,
  1341.               it normally prompts you with a popup asking you if it
  1342.               is OK to do this, since it takes time.
  1343.  
  1344.               Specify REGISTERSTATUS(Y) to tell NNMVS to go ahead and
  1345.               do this.  REGISTERSTATUS(N) says not to.  The default,
  1346.               REGISTERSTATUS(P), tells NNMVS to prompt as it would if
  1347.               you selected option R from the primary menu.
  1348.  
  1349. ))FORCE
  1350.  
  1351.               NNMVS tries to determine if there is a TCP/IP socket
  1352.               application active elsewhere in your TSO environment
  1353.               before starting up, to prevent TCP/IP errors.  If it
  1354.               tells you that there is another client active but in
  1355.               truth there is none and you know it, you can use the
  1356.               FORCE keyword to make NNMVS proceed whether it finds
  1357.               this to be the case or not.
  1358.  
  1359. ))DEBUG
  1360.  
  1361.               Set debugging mode on.  You must preallocate a file to
  1362.               ddname NNDEBUG for this to work.  This can be allocated
  1363.               to the terminal or a log file.  When debug mode is on,
  1364.               messages describing memory allocation and deallocation
  1365.               and NNTP commands sent are dumped to the debug file.
  1366.  
  1367. ))TEST
  1368.  
  1369.               Activate C/370 interactive test (INSPECT).  NNMVS must
  1370.               have been compiled with the TEST option for this to be
  1371.               effective.  Note that you can also issue the TEST command
  1372.               inside NNMVS to get to INSPECT, again provided that NNMVS
  1373.               was compiled with the TEST option.
  1374. ))BATCH
  1375.  
  1376.               Invoke NNMVS in batch mode.  When BATCH is specified,
  1377.               NEWSRC must also be specified.  The files specified by
  1378.               BATCHIN and BATCHOUT are allocated and you supply
  1379.               NNMVS batch commands in the BATCHIN file (typically the
  1380.               terminal).  You specify the news server via the command
  1381.  
  1382.               server = "foobar";
  1383.  
  1384.               where foobar should be replaced with the actual name of
  1385.               the NNTP server host.
  1386.  
  1387.               Note that no batch commands will be executed until the
  1388.               entire batch language program is read in and EOF is met.
  1389.  
  1390.               For help with the batch language, execute NNMVS in batch
  1391.               mode and supply the command "HELP".
  1392.  
  1393. ))BATCHIN('batch input file name')
  1394.  
  1395.               the data set allocated for input to NNMVS batch mode.
  1396.               Default is * (the terminal).
  1397.  
  1398.               Note that no batch commands will be executed until the
  1399.               entire batch language program is read in and EOF is met.
  1400.  
  1401.               For help with the batch language, execute NNMVS in batch
  1402.               mode and supply the command "HELP".
  1403.  
  1404. ))BATCHOUT('batch output file name')
  1405.  
  1406.               the data set allocated for output from NNMVS batch mode.
  1407.               Default is * (the terminal).
  1408.  
  1409.               For help with the batch language, execute NNMVS in batch
  1410.               mode and supply the command "HELP".
  1411.  
  1412. ))NEW
  1413.  
  1414.               Use a new (testing) release of NNMVS.  This is dependent
  1415.               upon your installation's procedures for providing
  1416.               parallel releases of software for users to run online in
  1417.               test mode.
  1418.  
  1419. ))OLD
  1420.  
  1421.               Use an old (backup) release of NNMVS.  This is dependent
  1422.               upon your installation's procedures for providing
  1423.               parallel releases of software for users to run online in
  1424.               test mode.
  1425.  
  1426. ./   ADD NAME=SIGFAIL,SSI=01010054
  1427.  
  1428. #include <stdio.h>
  1429. #include <stdlib.h>
  1430. #include <signal.h>
  1431.  
  1432. static void
  1433. handler() {
  1434.  printf("SIGINT handler has been called.\n");
  1435.  exit(8);
  1436. }
  1437.  
  1438. static int
  1439. ask(question)
  1440. char *question;
  1441. {
  1442.  char ans[81];
  1443.  
  1444.  for (;;) {
  1445.    printf("%s",question);
  1446.    fgets(ans,79,stdin);
  1447.    switch (ans[0]) {
  1448.      case 'y':
  1449.      case 'Y': return 1;
  1450.      case 'n':
  1451.      case 'N': return 0;
  1452.      default: printf("Bad answer, %s\n",ans);
  1453.               continue;
  1454.    }
  1455.  }
  1456. }
  1457.  
  1458. main(argc,argv)
  1459. int argc;
  1460. char **argv;
  1461. {
  1462.  int sigp;
  1463.  int loopp;
  1464.  int i;
  1465.  
  1466.  printf( 
  1467.   "This program demonstrates that SIGINT is not handled on MVS.\n");
  1468.  printf( 
  1469.   "It does NOT prove or disprove anything about attention handling\n");
  1470.  printf( 
  1471.   "in C/370 in general, except possibly for how output to stdout\n");
  1472.  printf( 
  1473.   "and stderr are affected by an attention interruption.\n\n");
  1474.  printf( 
  1475.   "At the end of the program, a line of output is written to each\n");
  1476.  printf( 
  1477.   "of the two output files.  If you see either one, that means that\n");
  1478.  printf( 
  1479.   "C/370 has intercepted the attention, but you will observe that\n");
  1480.  printf( 
  1481.   "it has not been handled by a SIGINT routine and it also has not\n");
  1482.  printf( 
  1483.   "allowed the program to be terminated by the operating system.\n\n");
  1484.  
  1485.  sigp  = ask("Do you want to signal abort on interrupts? (y or n)");
  1486.  loopp = ask("Do you want to loop forever without output? (y or n)");
  1487.  
  1488.  if (sigp) {
  1489.    printf("Doing signal(SIGINT,handler)\n");
  1490.    if (signal(SIGINT,handler) == SIG_ERR)
  1491.        perror("Could not set SIGINT");
  1492.  }
  1493.  
  1494.  printf("OK, hit PA1 now\n");
  1495.  
  1496.  if (loopp) {
  1497.    for (;;) ;
  1498.  }
  1499.  else {
  1500.    for (i=0;i<5000;i++) {
  1501.     printf("I=%d\n",i);
  1502.    }
  1503.  }
  1504.  printf("I'm finished (on stdout)\n");
  1505.  fprintf(stderr,"I'm finished (on stderr)\n");
  1506. }
  1507.  
  1508. ./ ENDUP 
  1509. ?!
  1510. //C        EXEC NNLOAD,TRK1='46',TO='C'
  1511. //SYSIN    DD DATA,DLM='?!'
  1512. ./   ADD NAME=NNMADDNG,SSI=01010043
  1513.  
  1514.  /********************************************************************/
  1515.  /*                                                                  */
  1516.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  1517.  /*                                                                  */
  1518.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  1519.  /* including the implied warranties of merchantability and fitness, */
  1520.  /* are expressly denied.                                            */
  1521.  /*                                                                  */
  1522.  /* Provided this copyright notice is included, this software may    */
  1523.  /* be freely distributed and not offered for sale.                  */
  1524.  /*                                                                  */
  1525.  /* Changes or modifications may be made and used only by the maker  */
  1526.  /* of same, and not further distributed.  Such modifications should */
  1527.  /* be mailed to the author for consideration for addition to the    */
  1528.  /* software and incorporation in subsequent releases.               */
  1529.  /*                                                                  */
  1530.  /********************************************************************/
  1531.  
  1532. #pragma  csect(code,  "NN@ADDNG")
  1533. #pragma  csect(static,"NN$ADDNG")
  1534.  
  1535. #include "nn.h"
  1536.  
  1537. #define KEEP_NEWSGROUPS_IN_ALPHABETICAL_ORDER
  1538.  
  1539. /****** Create a new newsgroup. **************************************/
  1540.  
  1541. static struct newsgroup *
  1542. new_newsgroup(np,gname)
  1543. Rstruc nncb         *np;
  1544. char                *gname;
  1545. {
  1546.  struct newsgroup   *gp;
  1547.  int                 gsize;
  1548.  char                temp [128];
  1549.  
  1550.  gsize = offsetof(struct newsgroup, name) + strlen(gname) + 1;
  1551.  
  1552.  sprintf(temp, "newsgroup %s", gname);
  1553.  GETMAIN(gp, char, gsize, temp);
  1554.  
  1555.  if (!gp) {
  1556.    ERR2("There is not enough memory to add newsgroup %s.",gname);
  1557.    return NULL;
  1558.  }
  1559.  
  1560.  memset(gp, 0, gsize);
  1561.  strcpy(gp->name, gname);
  1562.  ClearGroupStatus(gp);
  1563.  
  1564.  np->last_added_newsgroup = gp;
  1565.  
  1566.  return gp;
  1567.  
  1568. }
  1569.  
  1570. /****** Add newsgroup. ***********************************************/
  1571.  
  1572. struct newsgroup *
  1573. NNMaddng(np,gname)
  1574. Rstruc nncb         *np;
  1575. char                *gname;
  1576. {
  1577.  Rstruc newsgroup   *gp;
  1578.  struct newsgroup   *prev_gp;
  1579.  struct newsgroup   *next_gp;
  1580.  int                 s;
  1581.  
  1582.  /* If there are no newsgroups yet, make this the first one.       */
  1583.  /* If the newsgroup is currently in the newsgroup list, reuse it. */
  1584.  /* Otherwise add it. */
  1585.  
  1586.  if (np->first_newsgroup == NULL) {
  1587.    if ((gp=new_newsgroup(np,gname))) {
  1588.      np->first_newsgroup   = gp;
  1589.      np->current_newsgroup = gp;
  1590.      np->last_newsgroup    = gp;
  1591.    }
  1592.    return gp;
  1593.  }
  1594.  
  1595.  prev_gp = NULL;
  1596.  next_gp = NULL;
  1597.  
  1598.  
  1599. #ifdef KEEP_NEWSGROUPS_IN_ALPHABETICAL_ORDER
  1600.  
  1601.  /* Chances are this newsgroup will be right after the last one that
  1602.     we added.  Check there first. */
  1603.  
  1604.  gp = np->last_added_newsgroup;         /* search from last added  */
  1605.  if (!gp || strcmp(gname,gp->name) < 0) /* unless ours precedes it */
  1606.      gp = np->first_newsgroup;          /* then search from top    */
  1607.  
  1608.  for (; gp; gp = gp->next) {
  1609.    s = strcmp(gname,gp->name);
  1610.    if (s == 0)     { /* equal */
  1611.      np->current_newsgroup = gp;
  1612.      return gp;
  1613.    }
  1614.    else if (s < 0) { /* ours is less than theirs */
  1615.      next_gp = gp;
  1616.      break;
  1617.    }
  1618.    else            { /* ours is still greater */
  1619.      prev_gp = gp;
  1620.      next_gp = NULL;
  1621.    }
  1622.  }
  1623.  
  1624. #else
  1625.  
  1626.  /* keep newsgroups in NEWSRC order - not currently implemented */
  1627.  
  1628.  for (gp = np->first_newsgroup;
  1629.       gp && strcmp(gname,gp->name) != 0;
  1630.       gp = gp->next) ;
  1631.  
  1632.  if (gp) {   /* newsgroup already in list */
  1633.    np->current_newsgroup = gp;
  1634.    return gp;
  1635.  }
  1636.  
  1637.  next_gp = NULL;
  1638.  prev_gp = np->last_newsgroup;
  1639.  
  1640. #endif
  1641.  
  1642.  /* newsgroup not in list - add it now */
  1643.  
  1644.  if ((gp=new_newsgroup(np,gname))) {
  1645.  
  1646.    if (next_gp == NULL) np->last_newsgroup = gp;
  1647.    else                 gp->next = next_gp;
  1648.    if (prev_gp == NULL) np->first_newsgroup = gp;
  1649.    else                 prev_gp->next = gp;
  1650.  
  1651.    np->current_newsgroup = gp;
  1652.  }
  1653.  
  1654.  return gp;
  1655. }
  1656.  
  1657. ./   ADD NAME=NNMADJUA,SSI=01140047
  1658.  
  1659.  /********************************************************************/
  1660.  /*                                                                  */
  1661.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  1662.  /*                                                                  */
  1663.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  1664.  /* including the implied warranties of merchantability and fitness, */
  1665.  /* are expressly denied.                                            */
  1666.  /*                                                                  */
  1667.  /* Provided this copyright notice is included, this software may    */
  1668.  /* be freely distributed and not offered for sale.                  */
  1669.  /*                                                                  */
  1670.  /* Changes or modifications may be made and used only by the maker  */
  1671.  /* of same, and not further distributed.  Such modifications should */
  1672.  /* be mailed to the author for consideration for addition to the    */
  1673.  /* software and incorporation in subsequent releases.               */
  1674.  /*                                                                  */
  1675.  /********************************************************************/
  1676.  
  1677. #pragma  csect(code,  "NN@ADJUA")
  1678. #pragma  csect(static,"NN$ADJUA")
  1679. #include "nn.h"
  1680.  
  1681. /****** Adjust unread articles. **************************************/
  1682.  
  1683. void
  1684. NNMadjua(np,gp,count,first,last)
  1685. Rstruc nncb       *np;
  1686. Rstruc newsgroup  *gp;
  1687. int                count;   /* estimated article count        */
  1688. int                first;   /* estimated first article number */
  1689. int                last;    /* estimated last  article number */
  1690. {
  1691.  VARK             *vp;
  1692.  VARK             *vpfirst;
  1693.  VARK             *vplast;
  1694.  char             *nlp;
  1695.  
  1696.  /* logic:
  1697.   * case 
  1698.   *   last article number went up:      increment unread count
  1699.   *                                     update high number
  1700.   *                                     no need for new vector
  1701.   *   last article number went down:    need an article vector to
  1702.   *    see what newsrc says about which now-gone items were unread
  1703.   *
  1704.   * case 
  1705.   *   first article number went up:      need an article vector to
  1706.   *    see what newsrc says about which now-gone items were unread
  1707.   *   first article number went down:    impossible, nothing to do
  1708.   *
  1709.   */
  1710.  
  1711.  /* Do not change gp->high_number.  The caller of NNMadjua does this.
  1712.     NNMallav needs to see the old value. */
  1713.  
  1714.  if (last > gp->high_number) {
  1715.    gp->unread_count += (last - gp->high_number);
  1716.  }
  1717.  
  1718.  if (last < gp->high_number || first > gp->low_number) {
  1719.  
  1720.    /* Recent or oldest articles were cancelled or expired */
  1721.    /* Reset the count, since no GROUP request may be associated */
  1722.  
  1723.    /*
  1724.     * If NNTP LIST overriding NEWSRC spec, there is an unparsed
  1725.     * newsrc line.  If it's just of the form "<nnn" with nothing else,
  1726.     * and nnn is less than the new "low number" from LIST,
  1727.     * then bypass allocation of an article vector.  Just set the
  1728.     * unread count to the new high and low number.
  1729.     */
  1730.  
  1731.    if ((nlp=gp->saved_newsrc_line)
  1732.     && *nlp == '<'
  1733.     && !*(nlp+1 + strspn(nlp+1,"0123456789\n"))
  1734.     && atoi(nlp+1) < first) {
  1735.      gp->unread_count  = count;
  1736.    }
  1737.  
  1738.    /*
  1739.     * If the article count didn't come from the NNTP GROUP command,
  1740.     * then estimate it from the NNTP LIST or NEWSRC range, but only
  1741.     * if an article vector was allocated.
  1742.     */
  1743.  
  1744.    else {
  1745.  
  1746.      NNMallav(np,gp,first,last);    /* Allocate article vector */
  1747.  
  1748.      if (gp->article_vector && !GroupSelected(gp)) {
  1749.        gp->article_count = 0;
  1750.        vpfirst = &GETVARKFIRST(gp);
  1751.        vplast  = &GETVARKLAST(gp);
  1752.        for (vp = vpfirst; vp <= vplast; vp++) {
  1753.          if (IsPresent(*vp)) gp->article_count++;
  1754.        } 
  1755.      }
  1756.    }
  1757.  }
  1758.  else {
  1759.    gp->article_count = count;
  1760.  }
  1761.  
  1762.  /* No last minute adjustment of unread count,
  1763.   * since this produces bad results later.
  1764.   * If the user doesn't like this, hack the newsgroup display, not
  1765.   * the newsgroup structure.  What about saving back to newsrc?
  1766.   */
  1767.  
  1768.  /*
  1769.   * if (gp->unread_count > gp->article_count)
  1770.   *     gp->unread_count = gp->article_count;
  1771.   */
  1772.  
  1773.  return; 
  1774. }
  1775.  
  1776. ./   ADD NAME=NNMALLAV,SSI=011B0006
  1777.  
  1778.  /********************************************************************/
  1779.  /*                                                                  */
  1780.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  1781.  /*                                                                  */
  1782.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  1783.  /* including the implied warranties of merchantability and fitness, */
  1784.  /* are expressly denied.                                            */
  1785.  /*                                                                  */
  1786.  /* Provided this copyright notice is included, this software may    */
  1787.  /* be freely distributed and not offered for sale.                  */
  1788.  /*                                                                  */
  1789.  /* Changes or modifications may be made and used only by the maker  */
  1790.  /* of same, and not further distributed.  Such modifications should */
  1791.  /* be mailed to the author for consideration for addition to the    */
  1792.  /* software and incorporation in subsequent releases.               */
  1793.  /*                                                                  */
  1794.  /********************************************************************/
  1795.  
  1796. #pragma  csect(code,  "NN@ALLAV")
  1797. #pragma  csect(static,"NN$ALLAV")
  1798. #include "nn.h"
  1799.  
  1800. /****** Parse NEWSRC line. *******************************************/
  1801.  
  1802. static void
  1803. parse_newsrc_line(np,gp)
  1804. Rstruc nncb         *np;
  1805. Rstruc newsgroup    *gp;
  1806. {
  1807.  register char      *nlp                  = gp->saved_newsrc_line;
  1808.  int                 newsrc_number1       = 0;
  1809.  int                 newsrc_number2       = 0;
  1810.  int                 previous_number2     = 0;
  1811.  int                 newsrc_scan_count    = 0;
  1812.  int                 i;
  1813.  int                 imin;
  1814.  int                 imax;
  1815.  
  1816.  /*
  1817.   * Reset the unread count, throwing away the "newsrc_unread" value.
  1818.   * Initially the whole article vector is unread, and we make each
  1819.   * article read if it says so in the rest of the newsrc line.
  1820.   * Anything outside of the range of the article vector is GONE,
  1821.   * so we consider it READ (i.e. not unread).
  1822.   */
  1823.  
  1824.  gp->unread_count = gp->vector_last - gp->vector_first + 1;
  1825.  
  1826.  /* If there is no newsrc line to parse, that's all.  This used to be
  1827.     first in this routine, but that caused missing articles outside of
  1828.     the vector range not to be un-unread. */
  1829.  
  1830.  if (!nlp) {
  1831.    if (np->debug_file)
  1832.       fprintf(np->debug_file,"NNMallav: no saved newsrc line for %s\n",
  1833.                              gp->name);
  1834.    return;
  1835.  }
  1836.  
  1837.  /* get next number thing */
  1838.  
  1839.  while (*nlp) {
  1840.  
  1841.    previous_number2 = newsrc_number2;
  1842.  
  1843.    while (*nlp && isspace(*nlp)) nlp++;
  1844.  
  1845.    switch (*nlp) {
  1846.      case '\0': newsrc_number1 = MAX_INT;
  1847.                 newsrc_number2 = 0;
  1848.                 break;
  1849.      case '<':  sscanf(nlp," <%d %n",    &newsrc_number2,
  1850.                                          &newsrc_scan_count);
  1851.                 newsrc_number1 = 1;
  1852.                 nlp += newsrc_scan_count;
  1853.                 break;
  1854.      case '|':  sscanf(nlp," |%d=%d %n", &newsrc_number1,
  1855.                                          &newsrc_number2,
  1856.                                          &newsrc_scan_count);
  1857.                 nlp += newsrc_scan_count;
  1858.                 break;
  1859.      case '{':  nlp = strchr(++nlp,'}');
  1860.                 if (nlp) nlp++;
  1861.                 continue;
  1862.      case '#':  nlp = strchr(++nlp,'#');
  1863.                 if (nlp) nlp++;
  1864.                 continue;
  1865.      default:   sscanf(nlp," %d %n",     &newsrc_number1,
  1866.                                          &newsrc_scan_count);
  1867.                 newsrc_number2 = newsrc_number1;
  1868.                 nlp += newsrc_scan_count;
  1869.                 break;
  1870.    }
  1871.  
  1872.    /*
  1873.     * For this range of articles marked unread, if it's in the range
  1874.     * of the article vector, we do nothing (should have been UNREAD).
  1875.     */
  1876.  
  1877.    /*
  1878.     * For this range of articles marked read, if it's in the range
  1879.     * of the article vector, we mark the status accordingly.
  1880.     * If it's outside of the range of the article vector,
  1881.     * do nothing - it's just missing somehow.
  1882.     */
  1883.  
  1884.    imax = MAX(newsrc_number1,gp->vector_first);
  1885.    imin = MIN(newsrc_number2,gp->vector_last);
  1886.    for (i = imax; i <= imin; i++) {
  1887.      SetRead(GETVARK(gp,i));
  1888.      gp->unread_count--;
  1889.    }
  1890.  
  1891.  } /* end while */
  1892.  
  1893.  /* We're finished parsing the newsrc line, so free it. */
  1894.  
  1895.  if (gp->saved_newsrc_line != gp->saved_newsrc_data) {
  1896.    FREEMAIN(gp->saved_newsrc_line,"parsed newsrc line");
  1897.  }
  1898.  
  1899.  gp->saved_newsrc_line = NULL;
  1900.  gp->saved_newsrc_data[0] = '\0';
  1901.  
  1902.  return; 
  1903. }
  1904.  
  1905. /****** Allocate articles for newsgroup. *****************************/
  1906.  
  1907. void
  1908. NNMallav(np,gp,first,last)
  1909. Rstruc nncb         *np;
  1910. Rstruc newsgroup    *gp;
  1911. int                  first;
  1912. int                  last;
  1913. {
  1914.  VARK               *oldvp    = gp->article_vector;
  1915.  VARK               *newvp    = NULL;
  1916.  int                 oldfirst = gp->vector_first;
  1917.  int                 oldlast  = gp->vector_last;
  1918.  int                 newfirst = first;
  1919.  int                 newlast  = last;
  1920.  int                 oldvlen;
  1921.  int                 newvlen;
  1922.  int                 anum;
  1923.  int                 commonfirst;
  1924.  int                 commonlast;
  1925.  
  1926. /*
  1927.  * if an article vector already exists, then:
  1928.  *
  1929.  * all articles from new.first to old.first - 1 (impossible?) are
  1930.  *  set from their newsrc status, or else "unread"
  1931.  * all articles from old.first to new.first - 1 are UN-UNREAD.
  1932.  * all articles from old.last + 1 to new.last are:
  1933.  *  set to "unread" if > old.high_number
  1934.  *   (remember, we don't reset those until after the artvec hacking)
  1935.  *  set to "missing" ("read") if <= old.high_number
  1936.  *   (or unknown, or ???)
  1937.  * all articles from new.last + 1 to old.last are UN-UNREAD.
  1938.  */
  1939.  
  1940.  if (np->debug_file) {
  1941.    fprintf(np->debug_file,
  1942.            "NNMallav: asking for article vector for %s (%d, %d)\n",
  1943.            gp->name, first, last);
  1944.  }
  1945.  
  1946.  if (oldfirst == newfirst && oldlast == newlast) return;
  1947.  
  1948.  newvlen = (last == 0 ? 0 : last - first + 1);
  1949.  
  1950.  if (newvlen > 0) {
  1951.  
  1952.    GETMAIN(newvp, VARK, newvlen, "article vector");
  1953.  
  1954.    if (!newvp) {
  1955.      fprintf(stderr,"Error allocating %d-article vector for %s\n",
  1956.                     newvlen, gp->name);
  1957.      ERR1("There is not enough virtual memory available to proceed.");
  1958.      return;
  1959.    }
  1960.  
  1961.    memset(newvp, 0, newvlen * sizeof(VARK));
  1962.  
  1963.  }
  1964.  
  1965.  else {
  1966.    newfirst = 2147483647;
  1967.    newlast  = 0;
  1968.  }
  1969.  
  1970.  if (oldvp) {  /* if article vector already exists */
  1971.  
  1972.    commonfirst = MAX(oldfirst, newfirst);
  1973.    commonlast  = MIN(oldlast,  newlast);
  1974.  
  1975.   /*
  1976.    * copy the vector slots over from the old vector
  1977.    */
  1978.  
  1979.    for (anum=commonfirst; anum <= commonlast; anum++) {
  1980.      newvp[anum-newfirst] = oldvp[anum-oldfirst];
  1981.    }
  1982.  
  1983.   /*
  1984.    * all articles from new.first to old.first - 1 (impossible?) are
  1985.    *  set from their newsrc status, or else "unread"
  1986.    * Rationale: buggy newsrc didn't account for existing items
  1987.    * can't set from newsrc until NNMpnrl is executed, so set them
  1988.    * to good old missing-unread
  1989.    */
  1990.  
  1991.    for (anum = newfirst; anum <= newlast && anum < oldfirst; anum++) {
  1992.      SetMissingUnread(newvp[anum-newfirst]);
  1993.    }
  1994.  
  1995.   /*
  1996.    * all articles from old.first to new.first - 1 are UN-UNREAD.
  1997.    * Rationale: old items have expired or been cancelled.
  1998.    * Since they fall out of the vector, they don't get an explicit
  1999.    * status, but they do have to be removed from the unread count.
  2000.    */
  2001.  
  2002.    for (anum = oldfirst; anum <= oldlast && anum < newfirst; anum++) {
  2003.      if (IsUnread(oldvp[anum-oldfirst])) {
  2004.        gp->unread_count--;
  2005.      }
  2006.    }
  2007.  
  2008.   /*
  2009.    * all articles from old.last + 1 to new.last are:
  2010.    *  set to "unread" if > old.high_number
  2011.    *   Rationale: new items came in since last time we looked
  2012.    *  set to "missing" ("read") if <= old.high_number
  2013.    *   Rationale: items in range but don't exist, cancelled/expired
  2014.    */
  2015.  
  2016.    for (anum = MAX(newfirst, oldlast + 1); anum <= newlast; anum++) {
  2017.      if (anum > gp->high_number) SetUnread(newvp[anum-newfirst]);
  2018.      else                        SetMissingRead(newvp[anum-newfirst]);
  2019.    }
  2020.  
  2021.   /*
  2022.    * all articles from new.last + 1 to old.last are UN-UNREAD.
  2023.    * Rationale: old items have expired or been cancelled.
  2024.    * Since they fall out of the vector, they don't get an explicit
  2025.    * status, but they do have to be removed from the unread count.
  2026.    */
  2027.  
  2028.    for (anum = MAX(oldfirst, newlast + 1); anum <= oldlast; anum++) {
  2029.      if (IsUnread(oldvp[anum-oldfirst])) {
  2030.        gp->unread_count--;
  2031.      }
  2032.    }
  2033.  
  2034.    FREEMAIN(oldvp,"old article vector");
  2035.  
  2036.  }
  2037.  else {      /* no old article vector */
  2038.  
  2039.   /*
  2040.    * initialize the vector to all unknown and unread
  2041.    */
  2042.  
  2043.    for (anum = newfirst; anum <= newlast; anum++) {
  2044.      SetNull(newvp[anum-newfirst]);
  2045.    }
  2046.  
  2047.  }
  2048.  
  2049.  oldvlen = gp->article_vector_len;
  2050.  
  2051.  gp->article_vector     = newvp;
  2052.  gp->article_vector_len = newvlen;
  2053.  gp->vector_first       = first;
  2054.  gp->vector_last        = last;
  2055.  
  2056.  /* If this is the first time that we have allocated the article
  2057.   * vector, initialize it from the saved newsrc line if there is one.
  2058.   * i.e. if the article vector is being allocated for the first time.
  2059.   */
  2060.  
  2061.  if (oldvlen == 0) {
  2062.    parse_newsrc_line(np,gp);
  2063.  }
  2064.  
  2065.  return; 
  2066.  
  2067. }
  2068.  
  2069. ./   ADD NAME=NNMALLOC,SSI=01050033
  2070.  
  2071.  /********************************************************************/
  2072.  /*                                                                  */
  2073.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  2074.  /*                                                                  */
  2075.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  2076.  /* including the implied warranties of merchantability and fitness, */
  2077.  /* are expressly denied.                                            */
  2078.  /*                                                                  */
  2079.  /* Provided this copyright notice is included, this software may    */
  2080.  /* be freely distributed and not offered for sale.                  */
  2081.  /*                                                                  */
  2082.  /* Changes or modifications may be made and used only by the maker  */
  2083.  /* of same, and not further distributed.  Such modifications should */
  2084.  /* be mailed to the author for consideration for addition to the    */
  2085.  /* software and incorporation in subsequent releases.               */
  2086.  /*                                                                  */
  2087.  /********************************************************************/
  2088.  
  2089. #pragma  csect(code,  "NN@ALLOC")
  2090. #pragma  csect(static,"NN$ALLOC")
  2091. #include "nn.h"
  2092.  
  2093. /****** Allocate a data set. *****************************************/
  2094.  
  2095. Bool
  2096. NNMalloc(dsname,ddname,type,nitems)
  2097. char                      *dsname;
  2098. char                      *ddname;
  2099. enum data_set_type         type;
  2100. int                        nitems;
  2101. {
  2102.  int          i;
  2103.  int          rc;
  2104.  Bool         try_new;
  2105.  short        primary_allocation   ;
  2106.  short        secondary_allocation ;
  2107.  short        directory_blocks     ;
  2108.  short        dsorg                ;
  2109.  __S99parms   stuff99;   /* The manual has it wrong.  No "struct". */
  2110.  TEXTUNIT    *tu [17];
  2111.  TEXTUNIT     tu_dsn;
  2112.  TEXTUNIT     tu_ddn;
  2113.  TEXTUNIT     tu_member;
  2114.  TEXTUNIT     tu_stat;
  2115.  TEXTUNIT     tu_disp;
  2116.  TEXTUNIT     tu_perm;
  2117.  TEXTUNIT     tu_rtddn;
  2118.  TEXTUNIT     tu_rtorg;
  2119.  TEXTUNIT     tu_block;
  2120.  TEXTUNIT     tu_prime;
  2121.  TEXTUNIT     tu_sec;
  2122.  TEXTUNIT     tu_dir;
  2123.  TEXTUNIT     tu_recfm;
  2124.  TEXTUNIT     tu_lrecl;
  2125.  TEXTUNIT     tu_blksz;
  2126.  TEXTUNIT     tu_dsorg;
  2127.  char        *lparp;
  2128.  char        *rparp;
  2129.  char         dsnseq [81];
  2130.  char         member [81];
  2131.  
  2132.  try_new = FALSE;
  2133.  
  2134.  memset((char *)&stuff99,0,sizeof(__S99parms));
  2135.  
  2136.  strcpy(member,"");
  2137.  strcpy(dsnseq,dsname);
  2138.  lparp = strchr(dsnseq,'(');
  2139.  rparp = strchr(dsnseq,')');
  2140.  if (lparp && rparp && (lparp < rparp) && (*(rparp+1) == '\0')) {
  2141.    *lparp = '\0';            /* makes dsnseq the seq part only */
  2142.    *rparp = '\0';            /* turns member into a string     */
  2143.    strcpy(member, lparp+1);
  2144.    type = PDS;
  2145.  }
  2146.  
  2147.  for (;;) {
  2148.  
  2149.    stuff99.__S99RBLN   = 20;
  2150.    stuff99.__S99VERB   = S99VRBAL;
  2151.    stuff99.__S99FLAG1  = S99NOCNV << 8;
  2152.    stuff99.__S99ERROR  = 0;
  2153.    stuff99.__S99INFO   = 0;
  2154.    stuff99.__S99TXTPP  = tu;
  2155.    stuff99.__S99FLAG2  = 0;
  2156.  
  2157.    i = 0;
  2158.  
  2159.    tu[i++] = &tu_dsn;
  2160.  
  2161.    tu_dsn.key        = DALDSNAM;
  2162.    tu_dsn.num        = 1;
  2163.    tu_dsn.ent.len    = strlen(dsnseq);
  2164.    copy_uppercase(tu_dsn.ent.prm,dsnseq);
  2165.  
  2166.    tu[i++] = &tu_stat;
  2167.  
  2168.    tu_stat.key      = DALSTATS;
  2169.    tu_stat.num      = 1;
  2170.    tu_stat.ent.len  = 1;
  2171.    *tu_stat.ent.prm = (try_new ? NEW : SHR);
  2172.  
  2173.    tu[i++] = &tu_disp;
  2174.  
  2175.    tu_disp.key      = DALNDISP;
  2176.    tu_disp.num      = 1;
  2177.    tu_disp.ent.len  = 1;
  2178.    *tu_disp.ent.prm = (try_new ? CATLG : KEEP);
  2179.  
  2180.    tu[i++] = &tu_rtorg;
  2181.  
  2182.    tu_rtorg.key     = DALRTORG;
  2183.    tu_rtorg.num     = 1;
  2184.    tu_rtorg.ent.len = 2;
  2185.  
  2186.    if (*member) {
  2187.  
  2188.      tu[i++] = &tu_member;
  2189.  
  2190.      tu_member.key     = DALMEMBR;
  2191.      tu_member.num     = 1;
  2192.      tu_member.ent.len = strlen(member);
  2193.      copy_uppercase(tu_member.ent.prm,member);
  2194.  
  2195.    }
  2196.  
  2197.    if (ddname && *ddname) {
  2198.  
  2199.      tu[i++] = &tu_ddn;
  2200.  
  2201.      tu_ddn.key     = DALDDNAM;
  2202.      tu_ddn.num     = 1;
  2203.      tu_ddn.ent.len = strlen(ddname);
  2204.      copy_uppercase(tu_ddn.ent.prm,ddname);
  2205.  
  2206.      tu[i++] = &tu_perm;
  2207.  
  2208.      tu_perm.key     = DALPERMA;
  2209.      tu_perm.num     = 0;
  2210.    }
  2211.    else {
  2212.  
  2213.      tu[i++] = &tu_rtddn;
  2214.  
  2215.      tu_rtddn.key     = DALRTDDN;
  2216.      tu_rtddn.num     = 1;
  2217.      tu_rtddn.ent.len = 8;
  2218.      memset(tu_rtddn.ent.prm,' ',8);
  2219.  
  2220.    }
  2221.  
  2222.    if (try_new) {
  2223.  
  2224.      switch (type) {
  2225.        case PDS:
  2226.                  primary_allocation   = (short)nitems;
  2227.                  secondary_allocation = primary_allocation;
  2228.                  directory_blocks     = (short)((nitems/(12*36)+1)*36);
  2229.                  dsorg                = DSORG_PO;
  2230.                  break;
  2231.        case SEQ:
  2232.        default:
  2233.                  primary_allocation   = (short)nitems;
  2234.                  secondary_allocation = primary_allocation;
  2235.                  directory_blocks     = 0;
  2236.                  dsorg                = DSORG_PS;
  2237.                  break;
  2238.      }
  2239.  
  2240.      tu[i++] = &tu_block;
  2241.  
  2242.      tu_block.key     = DALBLKLN;
  2243.      tu_block.num     = 1;
  2244.      tu_block.ent.len = 3;
  2245.      memset(tu_block.ent.prm,0,3);
  2246.      *(short *)(tu_block.ent.prm+1) = 6233;
  2247.  
  2248.      tu[i++] = &tu_prime;
  2249.  
  2250.      tu_prime.key     = DALPRIME;
  2251.      tu_prime.num     = 1;
  2252.      tu_prime.ent.len = 3;
  2253.      memset(tu_prime.ent.prm,0,3);
  2254.      *(short *)(tu_prime.ent.prm+1) = primary_allocation;
  2255.  
  2256.      tu[i++] = &tu_sec;
  2257.  
  2258.      tu_sec.key     = DALSECND;
  2259.      tu_sec.num     = 1;
  2260.      tu_sec.ent.len = 3;
  2261.      memset(tu_sec.ent.prm,0,3);
  2262.      *(short *)(tu_sec.ent.prm+1) = secondary_allocation;
  2263.  
  2264.      tu[i++] = &tu_dir;
  2265.  
  2266.      tu_dir.key     = DALDIR;
  2267.      tu_dir.num     = 1;
  2268.      tu_dir.ent.len = 3;
  2269.      memset(tu_dir.ent.prm,0,3);
  2270.      *(short *)(tu_dir.ent.prm+1) = directory_blocks;
  2271.  
  2272.      tu[i++] = &tu_recfm;
  2273.  
  2274.      tu_recfm.key        = DALRECFM;
  2275.      tu_recfm.num        = 1;
  2276.      tu_recfm.ent.len    = 1;
  2277.      *tu_recfm.ent.prm   = RECFM_VB;
  2278.  
  2279.      tu[i++] = &tu_lrecl;
  2280.  
  2281.      tu_lrecl.key        = DALLRECL;
  2282.      tu_lrecl.num        = 1;
  2283.      tu_lrecl.ent.len    = 2;
  2284.      *(short *)tu_lrecl.ent.prm   = 259;
  2285.  
  2286.      tu[i++] = &tu_blksz;
  2287.  
  2288.      tu_blksz.key        = DALBLKSZ;
  2289.      tu_blksz.num        = 1;
  2290.      tu_blksz.ent.len    = 2;
  2291.      *(short *)tu_blksz.ent.prm   = 6233;
  2292.  
  2293.      tu[i++] = &tu_dsorg;
  2294.  
  2295.      tu_dsorg.key        = DALDSORG;
  2296.      tu_dsorg.num        = 1;
  2297.      tu_dsorg.ent.len    = 2;
  2298.      *(short *)tu_dsorg.ent.prm   = dsorg;
  2299.  
  2300.    }
  2301.  
  2302.    tu[i] = (void *)0x80000000;
  2303.  
  2304.    rc = svc99(&stuff99);
  2305.  
  2306.    if (rc == 0) {
  2307.      if (!(ddname && *ddname)) {
  2308.        memcpy(ddname,(char *)tu_rtddn.ent.prm,8);
  2309.        *(ddname+8) = ' ';
  2310.        *(strchr(ddname,' ')) = '\0';
  2311.      }
  2312.      if (type == SEQ &&
  2313.          tu_rtorg.ent.prm[0] != 0x40) {
  2314.        fprintf(stderr,"%s: not a sequential data set\n",dsname);
  2315.        return FALSE;
  2316.      }
  2317.      if (type == PDS &&
  2318.          tu_rtorg.ent.prm[0] != 0x02) {
  2319.        fprintf(stderr,"%s: not a partitioned data set\n",dsname);
  2320.        return FALSE;
  2321.      }
  2322.      return TRUE;
  2323.    }
  2324.    else if (!try_new && nitems != 0 && stuff99.__S99ERROR == 0x1708) {
  2325.     try_new = TRUE;
  2326.     continue;
  2327.    }
  2328.    else {
  2329.      NNMdfail(rc,&stuff99);
  2330.      return FALSE;
  2331.    }
  2332.  }
  2333. }
  2334.  
  2335. ./   ADD NAME=NNMAUTH,SSI=01070043
  2336.  
  2337.  /********************************************************************/
  2338.  /*                                                                  */
  2339.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  2340.  /*                                                                  */
  2341.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  2342.  /* including the implied warranties of merchantability and fitness, */
  2343.  /* are expressly denied.                                            */
  2344.  /*                                                                  */
  2345.  /* Provided this copyright notice is included, this software may    */
  2346.  /* be freely distributed and not offered for sale.                  */
  2347.  /*                                                                  */
  2348.  /* Changes or modifications may be made and used only by the maker  */
  2349.  /* of same, and not further distributed.  Such modifications should */
  2350.  /* be mailed to the author for consideration for addition to the    */
  2351.  /* software and incorporation in subsequent releases.               */
  2352.  /*                                                                  */
  2353.  /********************************************************************/
  2354.  
  2355. #pragma  csect(code,  "NN@AUTH ")
  2356. #pragma  csect(static,"NN$AUTH ")
  2357. #include "nn.h"
  2358.  
  2359. /****** Send authorization to news server. ***************************/
  2360.  
  2361. Bool
  2362. NNMauth(np)
  2363. Rstruc nncb *np;
  2364. {
  2365.  
  2366. #ifdef AUTHFILE
  2367.  
  2368.  char              *lp;
  2369.  FILE              *fp;
  2370.  int                display_rc;
  2371.  Bool               auth_error;
  2372.  Bool               connection_probably_closed;
  2373.  char               authdd    [12];
  2374.  char               authline [260];
  2375.  char               host      [65];
  2376.  char               user      [65];
  2377.  char               pass      [65];
  2378.  
  2379.  /* Send authorization.
  2380.   *
  2381.   * NNTP numbers must be the following as defined in C News source:
  2382.   *
  2383.   * OK_AUTHSYS    280  authorization system OK
  2384.   * OK_AUTH       281  authorization OK
  2385.   * NEED_AUTHINFO 380  authorization is required
  2386.   * NEED_AUTHDATA 381  <type> authorization data required (e.g. PASS)
  2387.   * ERR_NOAUTH    480  authorization required for command
  2388.   * ERR_AUTHSYS   481  authorization system invalid
  2389.   * ERR_AUTHREJ   482  authorization data rejected
  2390.   * ERR_CMDSYN    501  command syntax error
  2391.   * ERR_COMMAND   500  command not implemented
  2392.   * ERR_ACCESS    502  access to server denied
  2393.   * ERR_AUTHBAD   580  authorization failed
  2394.   *
  2395.   * Me:     AUTHINFO USER username
  2396.   * Server: 381 PASS required
  2397.   *     or: 482 Authorization already completed
  2398.   *     or: 500 Command not recognized
  2399.   *
  2400.   * If 482, server does not accept our attempt to gain authorization.
  2401.   *
  2402.   * If 500, authorization is not needed or the server has never
  2403.   * heard of authorization.  Either way, we proceed as "authorized".
  2404.   *
  2405.   * If 381 ...
  2406.   *
  2407.   * Me:     AUTHINFO PASS password
  2408.   * Server: 281 Authorization OK
  2409.   *     or: 482 authorization data rejected
  2410.   *     or: 502 access to server denied
  2411.   *     or: 580 authorization failed
  2412.   *
  2413.   * If 502, the server has disconnected me and I should return FALSE.
  2414.   * Otherwise, everything is OK, and I should return TRUE.
  2415.   *
  2416.   */
  2417.  
  2418.  lp = "None - local system error accessing authorization file";
  2419.  
  2420.  auth_error = FALSE;
  2421.  connection_probably_closed = FALSE;
  2422.  *host   = '\0';
  2423.  *user   = '\0';
  2424.  *pass   = '\0';
  2425.  
  2426.  /* Read user and pass from auth file */
  2427.  
  2428.  strcpy(authdd,"dd:");
  2429.  
  2430.  if (!NNMalloc(AUTHFILE,authdd+3,SEQ,0)) {  /* allocate as SHR */
  2431.    auth_error = TRUE;
  2432.  }
  2433.  else {
  2434.    if (!(fp=fopen(authdd,"r"))) {
  2435.      perror(AUTHFILE);
  2436.      auth_error = TRUE;
  2437.    }
  2438.    else {
  2439.      for (;;) {
  2440.        fgets(authline,sizeof(authline),fp);
  2441.        if (feof(fp)) break;
  2442.        if (ferror(fp)) {
  2443.          fprintf(stderr,"Error reading %s\n",AUTHFILE);
  2444.          auth_error = TRUE;
  2445.          break;
  2446.        } 
  2447.        if (authline[0] == '#') continue;      /* ignore comments */
  2448.        *host = '\0';
  2449.        *user = '\0';
  2450.        *pass = '\0';
  2451.        sscanf(authline,"%s %s %s", host,user,pass);
  2452.        uppercase_in_place(host);
  2453.        if (EQUAL(host,np->nnserver)) break;
  2454.      };
  2455.      fclose(fp);
  2456.    }
  2457.    (void)NNMunalc(authdd+3);
  2458.  }
  2459.  
  2460.  if (!auth_error) {
  2461.    if (*user == '\0') return TRUE;  /* Don't do auth if no username */
  2462.    sprintf(np->nntp_command,"AUTHINFO USER %s", user);
  2463.    if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
  2464.    if (!NNMgsrvl(np,&lp)) return FALSE;  /* Get server line */
  2465.    switch (np->nntp_message_num) {
  2466.      case 381: /* PASS required */
  2467.                break;
  2468.      case 500: /* Command not recognized */
  2469.                /* server does not support AUTHINFO - all clients OK */
  2470.                return TRUE;
  2471.      default:  NNMrperr(np);       /* Report protocol error */
  2472.                auth_error = TRUE;
  2473.                break;
  2474.    }
  2475.  }
  2476.  
  2477.  if (!auth_error) {
  2478.    sprintf(np->nntp_command,"AUTHINFO PASS %s", pass);
  2479.    if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
  2480.    if (!NNMgsrvl(np,&lp)) return FALSE;  /* Get server line */
  2481.    switch (np->nntp_message_num) {
  2482.      case 281: /* authorization OK */
  2483.                return TRUE;
  2484.      case 502: /* access to server denied */
  2485.                /* Also, we have been disconnected at this point. */
  2486.                connection_probably_closed = TRUE;
  2487.                auth_error = TRUE;
  2488.                break;
  2489.      default:  NNMrperr(np);       /* Report protocol error */
  2490.                auth_error = TRUE;
  2491.                break;
  2492.    }
  2493.  }
  2494.  
  2495.  NNMesrvr(np);                   /* End server read */
  2496.  
  2497.  if (auth_error) {
  2498.  
  2499.    if (connection_probably_closed) {
  2500.      ERR2("Authorization failed;\
  2501. The NNTP server at %s refuses to authorize you.  \
  2502. Some news operations may fail.",\
  2503.           np->nnserver);
  2504.      np->connection_broken = TRUE;
  2505.      NNMdisc(np);                  /* Complete disconnection */
  2506.      return FALSE;
  2507.    }
  2508.    else {
  2509.      if (np->batch_mode) {
  2510.        fprintf(stderr,
  2511.         "NNMVS could not obtain authorization from the NNTP server.\n");
  2512.        fprintf(stderr,
  2513.         "NNMVS will proceed, but some news operations may fail.\n");
  2514.        fprintf(stderr,
  2515.         "The response from server %s was:\n\n%s\n\n", np->nnserver,lp);
  2516.        return TRUE;
  2517.      }
  2518.      else {
  2519.        NNMivput(np,"NNSERVER ",np->nnserver,-1);
  2520.        NNMivput(np,"NNSRVRSP ",lp,          -1);
  2521.        (void)NNMispf(np,"ADDPOP ");
  2522.        (void)NNMispf(np,"DISPLAY PANEL(NNMPAUTH)");
  2523.        display_rc = np->ispfrc;
  2524.        (void)NNMispf(np,"REMPOP ");
  2525.        if (display_rc == 0) return TRUE;
  2526.        else {
  2527.          NNMdisc(np);
  2528.          return FALSE;
  2529.        } 
  2530.      }
  2531.    }
  2532.  
  2533.  }
  2534.  
  2535.  else return TRUE;
  2536.  
  2537. #else
  2538.  
  2539.  return TRUE;  /* no authorization file defined */
  2540.  
  2541. #endif
  2542.  
  2543. }
  2544.  
  2545. ./   ADD NAME=NNMBATCH,SSI=01000017
  2546.  
  2547.  /********************************************************************/
  2548.  /*                                                                  */
  2549.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  2550.  /*                                                                  */
  2551.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  2552.  /* including the implied warranties of merchantability and fitness, */
  2553.  /* are expressly denied.                                            */
  2554.  /*                                                                  */
  2555.  /* Provided this copyright notice is included, this software may    */
  2556.  /* be freely distributed and not offered for sale.                  */
  2557.  /*                                                                  */
  2558.  /* Changes or modifications may be made and used only by the maker  */
  2559.  /* of same, and not further distributed.  Such modifications should */
  2560.  /* be mailed to the author for consideration for addition to the    */
  2561.  /* software and incorporation in subsequent releases.               */
  2562.  /*                                                                  */
  2563.  /********************************************************************/
  2564.  
  2565. #pragma  csect(code,  "NN@BATCH")
  2566. #pragma  csect(static,"NN$BATCH")
  2567. #include "nn.h"
  2568. #include "nnbatch.h"
  2569.  
  2570. /****** Parse command. ***********************************************/
  2571.  
  2572. static void
  2573. parse_command(np,bp,proc)
  2574. Rstruc nncb         *np;
  2575. Rstruc batch        *bp;
  2576. CommandParser        proc;
  2577. {
  2578.  Rstruc newscmd     *cmdp = NULL;
  2579.  struct cmdtree     *treep;
  2580.  
  2581.  cmdp = (proc)(np,bp);
  2582.  
  2583.  if (!cmdp) return;
  2584.  
  2585.  /* If a newscmd structure was returned, add it to the cmd tree. */
  2586.  
  2587.  GETMAIN(treep, struct cmdtree, 1, "command tree");
  2588.  if (!treep) {
  2589.    bp->input_errors++;
  2590.    return;
  2591.  }
  2592.  
  2593.  treep->next = NULL;
  2594.  treep->cmd  = cmdp;
  2595.  
  2596.  if (bp->treebottom == NULL) bp->treetop = treep;
  2597.  else               bp->treebottom->next = treep;
  2598.  bp->treebottom = treep;
  2599.  
  2600.  return; 
  2601. }
  2602.  
  2603. /****** Process requests. ********************************************/
  2604.  
  2605. static void
  2606. process_requests(np,bp)
  2607. Rstruc nncb         *np;
  2608. Rstruc batch        *bp;
  2609. {
  2610.  Rstruc cmdtree     *treep;
  2611.  
  2612.  if (bp->treetop == NULL) {
  2613.    fprintf(np->batch_outfile, "There is no processing to be done.\n");
  2614.  }
  2615.  
  2616.  for (treep = bp->treetop; treep; treep = treep->next) {
  2617.    bp->runtime_error = FALSE;
  2618.    (treep->cmd->proc) (np,bp,treep->cmd);
  2619.    if (ferror(np->batch_outfile)) {
  2620.      fprintf(stderr,"*** Error writing to batch output file ***\n");
  2621.    }
  2622.    SETB("ERROR",bp->runtime_error);
  2623.  }
  2624.  
  2625.  return; 
  2626.  
  2627. }
  2628.  
  2629. /****** Flag unmatched END. ******************************************/
  2630.  
  2631. static struct newscmd *
  2632. flag_unmatched_end(np,bp)
  2633. Rstruc nncb         *np;
  2634. Rstruc batch        *bp;
  2635. {
  2636.  NNMbsynt(np,bp,NULL,0,"END without matching DO seen");
  2637.  
  2638.  return NULL;
  2639. }
  2640.  
  2641. /****** Flag invalid ISPLINK call. ***********************************/
  2642.  
  2643. static int
  2644. flag_invalid_isplink_call(service,argument)
  2645. char  *service;
  2646. char  *argument;
  2647. {
  2648.  fprintf(stderr,
  2649.          "*** Attempt to call ISPLINK in batch mode:\n%8.8s %8.8s\n",
  2650.          service, argument);
  2651.  
  2652.  return 20;
  2653. }
  2654.  
  2655. /****** Flag invalid ISPEXEC call. ***********************************/
  2656.  
  2657. static int
  2658. flag_invalid_ispexec_call(lenp,buf)
  2659. int   *lenp;
  2660. char  *buf;
  2661. {
  2662.  fprintf(stderr,"*** Attempt to call ISPEXEC in batch mode:\n%*.*s\n",
  2663.                 *lenp, *lenp, buf);
  2664.  return 20;
  2665. }
  2666.  
  2667. /****** NNMVS batch mode. ********************************************/
  2668.  
  2669. int
  2670. NNMbatch(np)
  2671. Rstruc nncb         *np;
  2672. {
  2673.  struct batch       *bp;
  2674.  char               *timep;
  2675.  char               *cp;
  2676.  CommandParser       proc;
  2677.  time_t              ltime;
  2678.  struct batch        batch_struct;
  2679.  
  2680.  static char         reserved_words [] = {
  2681.  "AND       DECLARE   DEREGISTERDO        ELSE      "
  2682.  "END       EQ        EXEC      EXTRACT   FALSE     "
  2683.  "FOR       GE        GT        HELP      IF        "
  2684.  "IN        LE        LT        MARK      NE        "
  2685.  "NNTP      NO        NOT       OFF       ON        "
  2686.  "OR        PUT       QUERY     QUIT      REGISTER  "
  2687.  "SET       THEN      TO        TRUE      VARS      "
  2688.  "WHEN      YES                "                     };
  2689.  
  2690.  if (!(np->batch_infile && np->batch_outfile)) {
  2691.    fprintf(stderr,"NNMVS: Batch operation failed.  Terminated.\n");
  2692.    return 16;
  2693.  }
  2694.  
  2695. #ifdef FETCH
  2696.  
  2697.    np->isplink_pointer = (int (*) ())flag_invalid_isplink_call;
  2698.    np->ispexec_pointer = (int (*) ())flag_invalid_ispexec_call;
  2699.  
  2700. #endif
  2701.  
  2702.  time(<ime);
  2703.  timep = ctime(<ime);
  2704.  if ((cp=strchr(timep,'\n'))) *cp = '\0';
  2705.  
  2706.  fprintf(np->batch_outfile,"NNMVS news client at %s - %s\n\n",
  2707.                            np->client_hostname, timep);
  2708.  
  2709.  bp = &batch_struct;
  2710.  np->batch_hook = bp;
  2711.  memset(bp,0,sizeof(struct batch));
  2712.  bp->reserved_words = reserved_words;
  2713.  bp->mode           = INITIAL_MODE;
  2714.  bp->curtok.type    = NO_TOKEN;
  2715.  bp->nextok.type    = NO_TOKEN;
  2716.  bp->endproc        = flag_unmatched_end;
  2717.  
  2718. #undef  TRUE
  2719. #define TRUE (void *)(1)
  2720.  
  2721.  /* Declare built-in variables along with initial values. */
  2722.  
  2723.  /* globally valid */
  2724.  
  2725.  NNMbdecl(np,bp,"LOCALPATH",    STRING_SYMTYPE, np->client_hostname);
  2726.  NNMbdecl(np,bp,"DATETIME",     STRING_SYMTYPE, timep      );
  2727.  NNMbdecl(np,bp,"SERVER",       STRING_SYMTYPE, ""         );
  2728.  NNMbdecl(np,bp,"OUTFILE",      STRING_SYMTYPE, ""         );
  2729.  NNMbdecl(np,bp,"SERVERLIST",   FLAG_SYMTYPE,   TRUE       );
  2730.  NNMbdecl(np,bp,"AUTOREGISTER", FLAG_SYMTYPE,   FALSE      );
  2731.  NNMbdecl(np,bp,"AUTODELETE",   FLAG_SYMTYPE,   TRUE       );
  2732.  NNMbdecl(np,bp,"AUTOMARK",     FLAG_SYMTYPE,   TRUE       );
  2733.  NNMbdecl(np,bp,"ERROR",        FLAG_SYMTYPE,   FALSE      );
  2734.  NNMbdecl(np,bp,"EXACTCASE",    FLAG_SYMTYPE,   FALSE      );
  2735.  NNMbdecl(np,bp,"TABEXPAND",    FLAG_SYMTYPE,   TRUE       );
  2736.  NNMbdecl(np,bp,"APPEND",       FLAG_SYMTYPE,   TRUE       );
  2737.  NNMbdecl(np,bp,"SEPARATOR",    STRING_SYMTYPE, ""         );
  2738.  NNMbdecl(np,bp,"BLANKSEP",     FLAG_SYMTYPE,   FALSE      );
  2739.  NNMbdecl(np,bp,"CHECKPOINT",   FLAG_SYMTYPE,   TRUE       );
  2740.  
  2741.  /* for newsgroups only */
  2742.  
  2743.  NNMbdecl(np,bp,"GROUP",        STRING_SYMTYPE, ""         );
  2744.  NNMbdecl(np,bp,"REGISTERED",   FLAG_SYMTYPE,   FALSE      );
  2745.  NNMbdecl(np,bp,"NEWGROUP",     FLAG_SYMTYPE,   FALSE      );
  2746.  NNMbdecl(np,bp,"NOSUCHGROUP",  FLAG_SYMTYPE,   FALSE      );
  2747.  NNMbdecl(np,bp,"COUNT",        NUMBER_SYMTYPE, 0          );
  2748.  NNMbdecl(np,bp,"UNREAD",       NUMBER_SYMTYPE, 0          );
  2749.  NNMbdecl(np,bp,"FIRST",        NUMBER_SYMTYPE, 0          );
  2750.  NNMbdecl(np,bp,"LAST",         NUMBER_SYMTYPE, 0          );
  2751.  
  2752.  /* for articles only */
  2753.  
  2754.  NNMbdecl(np,bp,"NUMBER",       NUMBER_SYMTYPE, 0          );
  2755.  NNMbdecl(np,bp,"READ",         FLAG_SYMTYPE,   FALSE      );
  2756.  NNMbdecl(np,bp,"MISSING",      FLAG_SYMTYPE,   FALSE      );
  2757.  NNMbdecl(np,bp,"SUBJECT",      STRING_SYMTYPE, ""         );
  2758.  NNMbdecl(np,bp,"DATE",         STRING_SYMTYPE, ""         );
  2759.  NNMbdecl(np,bp,"FROM",         STRING_SYMTYPE, ""         );
  2760.  NNMbdecl(np,bp,"MESSAGEID",    STRING_SYMTYPE, ""         );
  2761.  
  2762.  do {
  2763.    if ((proc = NNMbgcmd(np,bp))) {
  2764.      parse_command(np,bp,proc);
  2765.    }
  2766.  } while (!bp->eof);
  2767.  
  2768.  if (bp->input_errors > 0) {
  2769.    fprintf(np->batch_outfile, "\nNo processing due to input errors.\n");
  2770.    return 12;
  2771.  }
  2772.  
  2773.  else {
  2774.  
  2775.    fprintf(np->batch_outfile, "\n\nOpening NEWSRC...\n\n");
  2776.    strcpy(np->newsrc_to_open,"DD:NNNEWSRC");
  2777.    NNMonrf(np,NULL);                             /* Open NEWSRC file */
  2778.    fprintf(np->batch_outfile, "\n\nProcessing requests...\n\n");
  2779.    process_requests(np,bp);
  2780.    fprintf(np->batch_outfile, "\n\nClosing NEWSRC...\n\n");
  2781.    NNMcnrf(np,NULL,(Fool)TRUE);                /* Close  NEWSRC file */
  2782.  
  2783.  }
  2784.  
  2785.  /* Clean up any outfile hacking that may have been done. */
  2786.  
  2787.  SETC("OUTFILE","");
  2788.  (void)NNMbsout(np,bp);     /* Set output file */
  2789.  
  2790.  np->batch_hook = NULL;
  2791.  
  2792.  return bp->request_errors;
  2793.  
  2794. }
  2795.  
  2796. ./   ADD NAME=NNMBBEXP,SSI=01000017
  2797.  
  2798.  /********************************************************************/
  2799.  /*                                                                  */
  2800.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  2801.  /*                                                                  */
  2802.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  2803.  /* including the implied warranties of merchantability and fitness, */
  2804.  /* are expressly denied.                                            */
  2805.  /*                                                                  */
  2806.  /* Provided this copyright notice is included, this software may    */
  2807.  /* be freely distributed and not offered for sale.                  */
  2808.  /*                                                                  */
  2809.  /* Changes or modifications may be made and used only by the maker  */
  2810.  /* of same, and not further distributed.  Such modifications should */
  2811.  /* be mailed to the author for consideration for addition to the    */
  2812.  /* software and incorporation in subsequent releases.               */
  2813.  /*                                                                  */
  2814.  /********************************************************************/
  2815.  
  2816. #pragma  csect(code,  "NN@BBEXP")
  2817. #pragma  csect(static,"NN$BBEXP")
  2818. #include "nn.h"
  2819. #include "nnbatch.h"
  2820.  
  2821. #define CLEAR_THING(X) memset((char *)&X, 0, sizeof(struct thing))
  2822.  
  2823. static void from_exp      ();
  2824. static void from_choice   ();
  2825. static void from_relation ();
  2826. static void from_value    ();
  2827. static void from_quantity ();
  2828. static void from_term     ();
  2829. static void from_factor   ();
  2830. static void from_unop     ();
  2831. static void from_addop    ();
  2832. static void from_mulop    ();
  2833. static void from_logop    ();
  2834. static void from_relop    ();
  2835. static void from_constant ();
  2836. static void from_variable ();
  2837. static void from_number   ();
  2838. static void from_string   ();
  2839. static void from_flag     ();
  2840.  
  2841. /****** Free old value when replacing it with a new value. ***********/
  2842.  
  2843. #define free_old_value(A,B)  /* */
  2844.  
  2845. /* Do nothing yet.  This may not have been a malloc'd value...
  2846.  *
  2847.  *  static void
  2848.  *  free_old_value(np,tp)
  2849.  *  Rstruc nncb         *np;
  2850.  *  Rstruc thing        *tp;
  2851.  *  {
  2852.  *
  2853.  * if (tp->typ == STRING_SYMTYPE) {
  2854.  * FREEMAIN((char *)tp->val,"old intermediate expression string value");
  2855.  * tp->val = NULL;
  2856.  * }
  2857.  *
  2858.  * return;
  2859.  * }
  2860.  */
  2861.  
  2862. /****** Case-insensitive string compare. *****************************/
  2863.  
  2864. static int
  2865. Ustrcmp(a,b)
  2866. register char  *a;
  2867. register char  *b;
  2868. {
  2869.  register char  A;
  2870.  register char  B;
  2871.  
  2872.  while (*a || *b) {
  2873.    A = toupper(*a++);
  2874.    B = toupper(*b++);
  2875.    if (A > B) return 1;
  2876.    if (A < B) return -1;
  2877.  }
  2878.  
  2879.  return 0;
  2880. }
  2881.  
  2882. /****** Case-insensitive string search. ******************************/
  2883.  
  2884. static char *
  2885. Ustrstr(b,a)
  2886. register char  *b;
  2887. register char  *a;
  2888. {
  2889.  register char *aa;
  2890.  register char *bb;
  2891.  
  2892.  if (!*a) return strchr(b,'\0');
  2893.  for (;;) {
  2894.    while (*b && toupper(*a) != toupper(*b)) b++;
  2895.    if (!*b) return NULL;
  2896.    aa = a;
  2897.    bb = b;
  2898.    while (*aa && *bb && toupper(*aa) == toupper(*bb)) {
  2899.      aa++;
  2900.      bb++;
  2901.    }
  2902.    if (!*aa) return a;
  2903.    b++;
  2904.  }
  2905. }
  2906.  
  2907. /****** Concatenate string values. ***********************************/
  2908.  
  2909. static void
  2910. cat(np,bp,tp,tp1,tp2)
  2911. Rstruc nncb         *np;
  2912. Rstruc batch        *bp;
  2913. Rstruc thing        *tp;
  2914. Rstruc thing        *tp1;
  2915. Rstruc thing        *tp2;
  2916. {
  2917.  char               *strdata1;
  2918.  char               *strdata2;
  2919.  char               *newstr;
  2920.  int                 newlen;
  2921.  
  2922.  /* for now, just do a lot of getmains and freemains */
  2923.  
  2924.  free_old_value(np,tp);
  2925.  
  2926.  strdata1 = (char *)tp1->val;
  2927.  strdata2 = (char *)tp2->val;
  2928.  
  2929.  if (*strdata1 == '\0') {
  2930.    tp->val = (ANYTYPE)tp2->val;
  2931.  }
  2932.  else if (*strdata2 == '\0') {
  2933.    tp->val = (ANYTYPE)tp1->val;
  2934.  }
  2935.  else {
  2936.  
  2937.    newlen = strlen(strdata1) + strlen(strdata2) + 1;
  2938.  
  2939.    GETMAIN(newstr, 1, newlen, "new concatenated string");
  2940.  
  2941.    if (!newstr) {
  2942.      fprintf(np->batch_outfile,
  2943.       "Error, no storage to concatenate strings: %s, %s\n",
  2944.              tp1->val, tp2->val);
  2945.      longjmp(bp->jump,ERROR_GETMAIN_FAILURE);
  2946.    }
  2947.  
  2948.    strcpy(newstr,(char *)tp1->val);
  2949.    strcat(newstr,(char *)tp2->val);
  2950.  
  2951.    tp->val = (ANYTYPE)newstr;
  2952.  
  2953.  }
  2954.  
  2955.  tp->typ = STRING_SYMTYPE;
  2956.  free_old_value(np,tp1);
  2957.  free_old_value(np,tp2);
  2958.  return; 
  2959. }
  2960.  
  2961. /*-------------------------------------------------------------------*/
  2962.  
  2963. static void
  2964. convert_to_string(np,bp,tp)
  2965. Rstruc nncb         *np;
  2966. Rstruc batch        *bp;
  2967. Rstruc thing        *tp;
  2968. {
  2969.  Fool                tempflag;
  2970.  char                tempstr[17];
  2971.  
  2972.  switch (tp->typ) {
  2973.    case STRING_SYMTYPE: return;
  2974.    case NUMBER_SYMTYPE:
  2975.                         sprintf(tempstr, "%d", (int)tp->val);
  2976.                         tp->val = (ANYTYPE)NNMcopy(np,tempstr);
  2977.                         tp->typ = STRING_SYMTYPE;
  2978.                         return;
  2979.    case FLAG_SYMTYPE:
  2980.                         tempflag = (Fool)tp->val;
  2981.                         tp->val = tempflag ? (ANYTYPE)"TRUE"
  2982.                                            : (ANYTYPE)"FALSE";
  2983.                         tp->typ = STRING_SYMTYPE;
  2984.                         return;
  2985.  }
  2986. }
  2987.  
  2988. /*-------------------------------------------------------------------*/
  2989.  
  2990. static void
  2991. convert_to_number(np,bp,tp)
  2992. Rstruc nncb         *np;
  2993. Rstruc batch        *bp;
  2994. Rstruc thing        *tp;
  2995. {
  2996.  Fool                tempflag;
  2997.  
  2998.  switch (tp->typ) {
  2999.    case NUMBER_SYMTYPE: return;
  3000.    case FLAG_SYMTYPE:
  3001.                         tempflag = (Fool)tp->val;
  3002.                         tp->val = tempflag ? (ANYTYPE)1
  3003.                                            : (ANYTYPE)0;
  3004.                         tp->typ = NUMBER_SYMTYPE;
  3005.                         return;
  3006.    case STRING_SYMTYPE:
  3007.    /* Note: This should be permitted if the string is all numerics,
  3008.     *       but for now it is always an error.
  3009.     * If permitted, call free_old_value before altering.
  3010.     */
  3011.                         fprintf(np->batch_outfile,
  3012.              "Type mismatch, cannot convert string to number: %s\n",
  3013.                                 tp->val);
  3014.                         longjmp(bp->jump,ERROR_TYPE_MISMATCH);
  3015.  }
  3016. }
  3017.  
  3018. /*-------------------------------------------------------------------*/
  3019.  
  3020. static void
  3021. convert_to_flag(np,bp,tp)
  3022. Rstruc nncb         *np;
  3023. Rstruc batch        *bp;
  3024. Rstruc thing        *tp;
  3025. {
  3026.  
  3027.  switch (tp->typ) {
  3028.    case FLAG_SYMTYPE:   return;
  3029.    case NUMBER_SYMTYPE:
  3030.    /* Note: This should be permitted if the number is 0 or 1,
  3031.     *       but for now it is always an error.
  3032.     */
  3033.                         fprintf(np->batch_outfile,
  3034.              "Type mismatch, cannot convert number to flag: %d\n",
  3035.                                 tp->val);
  3036.                         longjmp(bp->jump,ERROR_TYPE_MISMATCH);
  3037.    case STRING_SYMTYPE:
  3038.    /* Note: This should be permitted if the string is "0", "1",
  3039.     *       "TRUE", "FALSE", "ON", "OFF", "YES", or "NO",
  3040.     *       but for now it is always an error.
  3041.     * If permitted, call free_old_value before altering.
  3042.     */
  3043.                         fprintf(np->batch_outfile,
  3044.              "Type mismatch, cannot convert string to flag: %s\n",
  3045.                                 tp->val);
  3046.                         longjmp(bp->jump,ERROR_TYPE_MISMATCH);
  3047.  }
  3048. }
  3049.  
  3050. /*-------------------------------------------------------------------*/
  3051.  
  3052. static void
  3053. from_number(np,bp,tp,p)
  3054. Rstruc nncb         *np;
  3055. Rstruc batch        *bp;
  3056. Rstruc thing        *tp;
  3057. Number               p;
  3058. {
  3059.  
  3060.  tp->val = (ANYTYPE)p->number1;
  3061.  tp->typ = NUMBER_SYMTYPE;
  3062.  return; 
  3063. }
  3064.  
  3065. /*-------------------------------------------------------------------*/
  3066.  
  3067. static void
  3068. from_string(np,bp,tp,p)
  3069. Rstruc nncb         *np;
  3070. Rstruc batch        *bp;
  3071. Rstruc thing        *tp;
  3072. String               p;
  3073. {
  3074.  
  3075.  tp->val = (ANYTYPE)p->string1;
  3076.  tp->typ = STRING_SYMTYPE;
  3077.  return; 
  3078. }
  3079.  
  3080. /*-------------------------------------------------------------------*/
  3081.  
  3082. static void
  3083. from_flag(np,bp,tp,p)
  3084. Rstruc nncb         *np;
  3085. Rstruc batch        *bp;
  3086. Rstruc thing        *tp;
  3087. Flag                 p;
  3088. {
  3089.  
  3090.  tp->val = (ANYTYPE)p->flag1;
  3091.  tp->typ = FLAG_SYMTYPE;
  3092.  return; 
  3093. }
  3094.  
  3095. /*-------------------------------------------------------------------*/
  3096.  
  3097. static void
  3098. from_variable(np,bp,tp,p)
  3099. Rstruc nncb         *np;
  3100. Rstruc batch        *bp;
  3101. Rstruc thing        *tp;
  3102. Variable             p;
  3103. {
  3104.  enum symtype        type;
  3105.  
  3106.  type = p->s;
  3107.  
  3108.  tp->val = (ANYTYPE)NNMbvget(np,bp,p->variable1,type);
  3109.  tp->typ = type;
  3110.  return; 
  3111. }
  3112.  
  3113. /*-------------------------------------------------------------------*/
  3114.  
  3115. static void
  3116. from_constant(np,bp,tp,p)
  3117. Rstruc nncb         *np;
  3118. Rstruc batch        *bp;
  3119. Rstruc thing        *tp;
  3120. Constant             p;
  3121. {
  3122.  
  3123.  switch (p->r) {
  3124.    case RHSTYPE_A: from_number(np,bp,tp,p->u.a.number1); break;
  3125.    case RHSTYPE_B: from_string(np,bp,tp,p->u.b.string1); break;
  3126.    case RHSTYPE_C: from_flag  (np,bp,tp,p->u.c.flag1  ); break;
  3127.  }
  3128.  
  3129.  return; 
  3130. }
  3131.  
  3132. /*-------------------------------------------------------------------*/
  3133.  
  3134. static void
  3135. from_factor(np,bp,tp,p)
  3136. Rstruc nncb         *np;
  3137. Rstruc batch        *bp;
  3138. Rstruc thing        *tp;
  3139. Factor               p;
  3140. {
  3141.  struct thing        t1;
  3142.  
  3143.  switch (p->r) {
  3144.    case RHSTYPE_A: from_constant(np,bp,tp,p->u.a.constant1); break;
  3145.    case RHSTYPE_B: from_variable(np,bp,tp,p->u.b.variable1); break;
  3146.    case RHSTYPE_C:
  3147.                    CLEAR_THING(t1);
  3148.                    from_factor(np,bp,&t1,p->u.c.factor2);
  3149.                    switch (p->u.c.unop1->op1) {
  3150.                      case ADD_OP:
  3151.                                   convert_to_number(np,bp,&t1);
  3152.                                   tp->val = t1.val;
  3153.                                   tp->typ = NUMBER_SYMTYPE;
  3154.                                   break;
  3155.                      case SUB_OP:
  3156.                                   convert_to_number(np,bp,&t1);
  3157.                                   tp->val = (ANYTYPE)
  3158.                                             (-((int)t1.val));
  3159.                                   tp->typ = NUMBER_SYMTYPE;
  3160.                                   break;
  3161.                      case NOT_OP:
  3162.                                   convert_to_flag(np,bp,&t1);
  3163.                                   tp->val = (ANYTYPE)
  3164.                                             (!((Fool)t1.val));
  3165.                                   tp->typ = FLAG_SYMTYPE;
  3166.                                   break;
  3167.                    }
  3168.                    break;
  3169.    case RHSTYPE_D: from_exp(np,bp,tp,p->u.d.exp1); break;
  3170.  }
  3171.  
  3172.  return; 
  3173. }
  3174.  
  3175. /*-------------------------------------------------------------------*/
  3176.  
  3177. static void
  3178. from_term(np,bp,tp,p)
  3179. Rstruc nncb         *np;
  3180. Rstruc batch        *bp;
  3181. Rstruc thing        *tp;
  3182. Term                 p;
  3183. {
  3184.  struct thing        t1;
  3185.  struct thing        t3;
  3186.  
  3187.  switch (p->r) {
  3188.    case RHSTYPE_A: from_factor(np,bp,tp,p->u.a.factor1); break;
  3189.    case RHSTYPE_B:
  3190.                    CLEAR_THING(t1);
  3191.                    CLEAR_THING(t3);
  3192.                    from_term  (np,bp,&t1,p->u.b.term1  );
  3193.                    from_factor(np,bp,&t3,p->u.b.factor3);
  3194.                    convert_to_number(np,bp,&t1);
  3195.                    convert_to_number(np,bp,&t3);
  3196.                    switch (p->u.b.mulop2->op1) {
  3197.                      case MUL_OP:
  3198.                                   /* how to detect overflow? */
  3199.                                   tp->val = (ANYTYPE)
  3200.                                             ((int)t1.val * (int)t3.val);
  3201.                                   break;
  3202.                      case DIV_OP:
  3203.                                   if ((int)t3.val == 0) {
  3204.                                     fprintf(np->batch_outfile,
  3205.                                "Arithmetic error, division by zero\n");
  3206.                                     longjmp(bp->jump,ERROR_ZERODIVIDE);
  3207.                                   }
  3208.                                   tp->val = (ANYTYPE)
  3209.                                             ((int)t1.val / (int)t3.val);
  3210.                                   break;
  3211.                    }
  3212.                    tp->typ = NUMBER_SYMTYPE;
  3213.                    break;
  3214.  }
  3215.  
  3216.  return; 
  3217. }
  3218.  
  3219. /*-------------------------------------------------------------------*/
  3220.  
  3221. static void
  3222. from_quantity(np,bp,tp,p)
  3223. Rstruc nncb         *np;
  3224. Rstruc batch        *bp;
  3225. Rstruc thing        *tp;
  3226. Quantity             p;
  3227. {
  3228.  struct thing        t1;
  3229.  struct thing        t3;
  3230.  
  3231.  switch (p->r) {
  3232.    case RHSTYPE_A: from_term(np,bp,tp,p->u.a.term1); break;
  3233.    case RHSTYPE_B:
  3234.                    CLEAR_THING(t1);
  3235.                    CLEAR_THING(t3);
  3236.                    from_quantity(np,bp,&t1,p->u.b.quantity1);
  3237.                    from_term    (np,bp,&t3,p->u.b.term3);
  3238.                    convert_to_number(np,bp,&t1);
  3239.                    convert_to_number(np,bp,&t3);
  3240.                    switch (p->u.b.addop2->op1) {
  3241.                      case ADD_OP:
  3242.                                   /* how to detect overflow? */
  3243.                                   tp->val = (ANYTYPE)
  3244.                                             ((int)t1.val + (int)t3.val);
  3245.                                   break;
  3246.                      case SUB_OP:
  3247.                                   /* how to detect overflow? */
  3248.                                   tp->val = (ANYTYPE)
  3249.                                             ((int)t1.val - (int)t3.val);
  3250.                                   break;
  3251.                    }
  3252.                    tp->typ = NUMBER_SYMTYPE;
  3253.                    break;
  3254.  }
  3255.  
  3256.  return; 
  3257. }
  3258.  
  3259. /*-------------------------------------------------------------------*/
  3260.  
  3261. static void
  3262. from_value(np,bp,tp,p)
  3263. Rstruc nncb         *np;
  3264. Rstruc batch        *bp;
  3265. Rstruc thing        *tp;
  3266. Value                p;
  3267. {
  3268.  struct thing        t1;
  3269.  struct thing        t2;
  3270.  
  3271.  switch (p->r) {
  3272.    case RHSTYPE_A: from_quantity(np,bp,tp,p->u.a.quantity1); break;
  3273.    case RHSTYPE_B:
  3274.                    CLEAR_THING(t1);
  3275.                    CLEAR_THING(t2);
  3276.                    from_value   (np,bp,&t1,p->u.b.value1);
  3277.                    from_quantity(np,bp,&t2,p->u.b.quantity2);
  3278.                    convert_to_string(np,bp,&t1);
  3279.                    convert_to_string(np,bp,&t2);
  3280.                    cat(np,bp,tp,&t1,&t2);
  3281.                    break;
  3282.  }
  3283.  
  3284.  return; 
  3285. }
  3286.  
  3287. /*-------------------------------------------------------------------*/
  3288.  
  3289. static void
  3290. from_relation(np,bp,tp,p)
  3291. Rstruc nncb         *np;
  3292. Rstruc batch        *bp;
  3293. Rstruc thing        *tp;
  3294. Relation             p;
  3295. {
  3296.  enum optype         op;
  3297.  struct thing        t1;
  3298.  struct thing        t3;
  3299.  
  3300.  switch (p->r) {
  3301.    case RHSTYPE_A: from_value(np,bp,tp,p->u.a.value1); break;
  3302.    case RHSTYPE_B:
  3303.         CLEAR_THING(t1);
  3304.         CLEAR_THING(t3);
  3305.         from_value(np,bp,&t1,p->u.b.value1);
  3306.         from_value(np,bp,&t3,p->u.b.value3);
  3307.         /* If either value is a string,
  3308.          * or operation is "IN", do string compare.
  3309.          * Otherwise do numeric compare.
  3310.          * Note: Currently we are case sensitive.
  3311.          *       This possibly should be changed, but
  3312.          *       not now...
  3313.          */
  3314.         op = p->u.b.relop2->op1;
  3315.         if (op == IN_OP
  3316.          || t1.typ == STRING_SYMTYPE
  3317.          || t3.typ == STRING_SYMTYPE) {
  3318.           convert_to_string(np,bp,&t1);
  3319.           convert_to_string(np,bp,&t3);
  3320.           if (bp->exactcase) {
  3321.             switch (op) {
  3322.               case EQ_OP: tp->val = (ANYTYPE)
  3323.                           (strcmp((char *)t1.val,(char *)t3.val) == 0);
  3324.                           break;
  3325.               case NE_OP: tp->val = (ANYTYPE)
  3326.                           (strcmp((char *)t1.val,(char *)t3.val) != 0);
  3327.                           break;
  3328.               case GT_OP: tp->val = (ANYTYPE)
  3329.                           (strcmp((char *)t1.val,(char *)t3.val) >  0);
  3330.                           break;
  3331.               case LT_OP: tp->val = (ANYTYPE)
  3332.                           (strcmp((char *)t1.val,(char *)t3.val) <  0);
  3333.                           break;
  3334.               case GE_OP: tp->val = (ANYTYPE)
  3335.                           (strcmp((char *)t1.val,(char *)t3.val) >= 0);
  3336.                           break;
  3337.               case LE_OP: tp->val = (ANYTYPE)
  3338.                           (strcmp((char *)t1.val,(char *)t3.val) <= 0);
  3339.                           break;
  3340.               case IN_OP: tp->val = (ANYTYPE)
  3341.                           (strstr((char *)t3.val,(char *)t1.val)!=NULL);
  3342.                           break;
  3343.             }
  3344.           }
  3345.           else {
  3346.             switch (op) {
  3347.               case EQ_OP: tp->val = (ANYTYPE)
  3348.                          (Ustrcmp((char *)t1.val,(char *)t3.val) == 0);
  3349.                           break;
  3350.               case NE_OP: tp->val = (ANYTYPE)
  3351.                          (Ustrcmp((char *)t1.val,(char *)t3.val) != 0);
  3352.                           break;
  3353.               case GT_OP: tp->val = (ANYTYPE)
  3354.                          (Ustrcmp((char *)t1.val,(char *)t3.val) >  0);
  3355.                           break;
  3356.               case LT_OP: tp->val = (ANYTYPE)
  3357.                          (Ustrcmp((char *)t1.val,(char *)t3.val) <  0);
  3358.                           break;
  3359.               case GE_OP: tp->val = (ANYTYPE)
  3360.                          (Ustrcmp((char *)t1.val,(char *)t3.val) >= 0);
  3361.                           break;
  3362.               case LE_OP: tp->val = (ANYTYPE)
  3363.                          (Ustrcmp((char *)t1.val,(char *)t3.val) <= 0);
  3364.                           break;
  3365.               case IN_OP: tp->val = (ANYTYPE)
  3366.                          (Ustrstr((char *)t3.val,(char *)t1.val)!=NULL);
  3367.                           break;
  3368.             }
  3369.           }
  3370.         }
  3371.         else {
  3372.           convert_to_number(np,bp,&t1);
  3373.           convert_to_number(np,bp,&t3);
  3374.           switch (op) {
  3375.             case EQ_OP: tp->val = (ANYTYPE)((int)t1.val == (int)t3.val);
  3376.                         break;
  3377.             case NE_OP: tp->val = (ANYTYPE)((int)t1.val != (int)t3.val);
  3378.                         break;
  3379.             case GT_OP: tp->val = (ANYTYPE)((int)t1.val >  (int)t3.val);
  3380.                         break;
  3381.             case LT_OP: tp->val = (ANYTYPE)((int)t1.val <  (int)t3.val);
  3382.                         break;
  3383.             case GE_OP: tp->val = (ANYTYPE)((int)t1.val >= (int)t3.val);
  3384.                         break;
  3385.             case LE_OP: tp->val = (ANYTYPE)((int)t1.val <= (int)t3.val);
  3386.                         break;
  3387.           }
  3388.         }
  3389.         tp->typ = FLAG_SYMTYPE;
  3390.         break;
  3391.  }
  3392.  
  3393.  return; 
  3394. }
  3395.  
  3396. /*-------------------------------------------------------------------*/
  3397.  
  3398. static void
  3399. from_choice(np,bp,tp,p)
  3400. Rstruc nncb         *np;
  3401. Rstruc batch        *bp;
  3402. Rstruc thing        *tp;
  3403. Choice               p;
  3404. {
  3405.  struct thing        t1;
  3406.  struct thing        t3;
  3407.  
  3408.  switch (p->r) {
  3409.    case RHSTYPE_A: from_relation(np,bp,tp,p->u.a.relation1); break;
  3410.    case RHSTYPE_B:
  3411.         CLEAR_THING(t1);
  3412.         CLEAR_THING(t3);
  3413.         from_choice  (np,bp,&t1,p->u.b.choice1);
  3414.         from_relation(np,bp,&t3,p->u.b.relation3);
  3415.         convert_to_flag(np,bp,&t1);
  3416.         convert_to_flag(np,bp,&t3);
  3417.         switch (p->u.b.logop2->op1) {
  3418.           case AND_OP:
  3419.                        tp->val = (ANYTYPE)
  3420.                                  ((Fool)t1.val && (Fool)t3.val);
  3421.                        break;
  3422.           case OR_OP:
  3423.                        tp->val = (ANYTYPE)
  3424.                                  ((Fool)t1.val || (Fool)t3.val);
  3425.                        break;
  3426.         }
  3427.         tp->typ = FLAG_SYMTYPE;
  3428.         break;
  3429.  }
  3430.  
  3431.  return; 
  3432. }
  3433.  
  3434. /*-------------------------------------------------------------------*/
  3435.  
  3436. static void
  3437. from_exp(np,bp,tp,p)
  3438. Rstruc nncb         *np;
  3439. Rstruc batch        *bp;
  3440. Rstruc thing        *tp;
  3441. Exp                  p;
  3442. {
  3443.  struct thing        t1;
  3444.  struct thing        t2;
  3445.  struct thing        t3;
  3446.  
  3447.  switch (p->r) {
  3448.    case RHSTYPE_A: from_choice(np,bp,tp,p->u.a.choice1); break;
  3449.    case RHSTYPE_B:
  3450.         CLEAR_THING(t1);
  3451.         CLEAR_THING(t2);
  3452.         CLEAR_THING(t3);
  3453.         from_exp(np,bp,&t1,p->u.b.exp1);
  3454.         from_exp(np,bp,&t2,p->u.b.exp2);
  3455.         from_exp(np,bp,&t3,p->u.b.exp3);
  3456.         convert_to_flag(np,bp,&t1);
  3457.         if ((Fool)t1.val) {
  3458.           tp->val = t2.val;
  3459.           tp->typ = t2.typ;
  3460.         }
  3461.         else {
  3462.           tp->val = t3.val;
  3463.           tp->typ = t3.typ;
  3464.         }
  3465.         break;
  3466.  }
  3467.  
  3468.  return; 
  3469. }
  3470.  
  3471. /****** Build object from ptree to return as run-time value. *********/
  3472.  
  3473. ANYTYPE
  3474. NNMbbexp(np,bp,treep,type)
  3475. Rstruc nncb         *np;
  3476. Rstruc batch        *bp;
  3477. Rstruc ptree        *treep;
  3478. enum symtype         type;
  3479. {
  3480.  struct thing        it;
  3481.  
  3482.  CLEAR_THING(it);
  3483.  
  3484.  bp->exactcase = GETB("EXACTCASE");
  3485.  
  3486.  /* Define return point for run-time errors during evaluation. */
  3487.  
  3488.  if (setjmp(bp->jump) != 0) {
  3489.    bp->request_errors++;
  3490.    bp->runtime_error = TRUE;
  3491.    return NULL;
  3492.  }
  3493.  
  3494.  /* Get the value, whatever type it turns out to be. */
  3495.  
  3496.  from_exp(np,bp,&it,treep->exp1);
  3497.  
  3498.  /* Try to make the value match the requested type. */
  3499.  
  3500.  switch (type) {
  3501.  
  3502.    case STRING_SYMTYPE: convert_to_string(np,bp,&it); break;
  3503.    case NUMBER_SYMTYPE: convert_to_number(np,bp,&it); break;
  3504.    case   FLAG_SYMTYPE: convert_to_flag  (np,bp,&it); break;
  3505.  
  3506.  }
  3507.  
  3508.  /* Return the value. */
  3509.  
  3510.  return it.val;
  3511.  
  3512. }
  3513.  
  3514. ./   ADD NAME=NNMBCONN,SSI=01000038
  3515.  
  3516.  /********************************************************************/
  3517.  /*                                                                  */
  3518.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  3519.  /*                                                                  */
  3520.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  3521.  /* including the implied warranties of merchantability and fitness, */
  3522.  /* are expressly denied.                                            */
  3523.  /*                                                                  */
  3524.  /* Provided this copyright notice is included, this software may    */
  3525.  /* be freely distributed and not offered for sale.                  */
  3526.  /*                                                                  */
  3527.  /* Changes or modifications may be made and used only by the maker  */
  3528.  /* of same, and not further distributed.  Such modifications should */
  3529.  /* be mailed to the author for consideration for addition to the    */
  3530.  /* software and incorporation in subsequent releases.               */
  3531.  /*                                                                  */
  3532.  /********************************************************************/
  3533.  
  3534. #pragma  csect(code,  "NN@BCONN")
  3535. #pragma  csect(static,"NN$BCONN")
  3536. #include "nn.h"
  3537. #include "nnbatch.h"
  3538.  
  3539. /****** Insure server name. ******************************************/
  3540.  
  3541. static void
  3542. insure_server_name(np,bp)
  3543. Rstruc nncb         *np;
  3544. Rstruc batch        *bp;
  3545. {
  3546.  char               *servername;
  3547.  
  3548.  if (!*np->nnserver) {
  3549.    servername = GETC("SERVER");
  3550.    if (servername) {
  3551.      strncpy(np->nnserver,servername,sizeof(np->nnserver));
  3552.    }
  3553.  }
  3554.  
  3555.  return; 
  3556. }
  3557.  
  3558. /****** Connect to server in batch mode. *****************************/
  3559.  
  3560. Bool
  3561. NNMbconn(np,bp)
  3562. Rstruc nncb         *np;
  3563. Rstruc batch        *bp;
  3564. {
  3565.  
  3566.  if (!np->connected_to_server) {
  3567.    insure_server_name(np,bp);
  3568.    if (!NNMconn(np)) {              /* Connect to server */
  3569.      fprintf(np->batch_outfile,"Server connection failed.\n");
  3570.      return FALSE;
  3571.    }
  3572.  }
  3573.  
  3574.  return np->connected_to_server;
  3575. }
  3576.  
  3577. ./   ADD NAME=NNMBDECL,SSI=01000011
  3578.  
  3579.  /********************************************************************/
  3580.  /*                                                                  */
  3581.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  3582.  /*                                                                  */
  3583.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  3584.  /* including the implied warranties of merchantability and fitness, */
  3585.  /* are expressly denied.                                            */
  3586.  /*                                                                  */
  3587.  /* Provided this copyright notice is included, this software may    */
  3588.  /* be freely distributed and not offered for sale.                  */
  3589.  /*                                                                  */
  3590.  /* Changes or modifications may be made and used only by the maker  */
  3591.  /* of same, and not further distributed.  Such modifications should */
  3592.  /* be mailed to the author for consideration for addition to the    */
  3593.  /* software and incorporation in subsequent releases.               */
  3594.  /*                                                                  */
  3595.  /********************************************************************/
  3596.  
  3597. #pragma  csect(code,  "NN@BDECL")
  3598. #pragma  csect(static,"NN$BDECL")
  3599. #include "nn.h"
  3600. #include "nnbatch.h"
  3601.  
  3602. /****** Validate a variable name. ************************************/
  3603.  
  3604. static Bool
  3605. validate(np,bp,var)
  3606. Rstruc nncb         *np;
  3607. Rstruc batch        *bp;
  3608. char                *var;
  3609. {
  3610.  int                 varlen;
  3611.  char               *cp;
  3612.  char                vartest[MAX_RESERVED_WORD_LENGTH];
  3613.  
  3614.  varlen = strlen(var);
  3615.  if (varlen < 1 || varlen > MAX_SYMBOL_LENGTH) {
  3616.    ERR2( 
  3617.     "A variable name must be between 1 and %d characters in length.",
  3618.         MAX_SYMBOL_LENGTH);
  3619.    return FALSE;
  3620.  }
  3621.  
  3622.  if (varlen >= MIN_RESERVED_WORD_LENGTH
  3623.   && varlen <= MAX_RESERVED_WORD_LENGTH) {
  3624.  
  3625.    memset(vartest,' ',MAX_RESERVED_WORD_LENGTH);
  3626.    memcpy(vartest,var,strlen(var));
  3627.  
  3628.    for (cp = bp->reserved_words; *cp != ' '; cp += 10) {
  3629.      if (memcmp(vartest,cp,MAX_RESERVED_WORD_LENGTH) == 0) {
  3630.        ERR2(
  3631.     "The name %s is reserved and cannot be used as a variable name.",
  3632.             var);
  3633.        return FALSE;
  3634.      }
  3635.    }
  3636.  }
  3637.  
  3638.  return TRUE;
  3639. }
  3640.  
  3641. /****** Declare a variable symbol. ***********************************/
  3642.  
  3643. struct symtab *
  3644. NNMbdecl(np,bp,var,type,val)
  3645. Rstruc nncb         *np;
  3646. Rstruc batch        *bp;
  3647. char                *var;
  3648. enum symtype         type;
  3649. ANYTYPE              val;
  3650. {
  3651.  Rstruc symtab      *symp;
  3652.  Rstruc symtab     **sympref;
  3653.  struct symtab      *sympnew;
  3654.  struct symtab      *sympleft;
  3655.  struct symtab      *sympright;
  3656.  int                 minimum_value_length;
  3657.  int                 getlen;
  3658.  int                 comp;
  3659.  char                vartest[MAX_SYMBOL_LENGTH];
  3660.  
  3661.  if (!validate(np,bp,var)) {
  3662.    NNMbsynt(np,bp,var,0,"Variable name cannot be declared");
  3663.    return NULL;
  3664.  }
  3665.  memset(vartest,'\0',MAX_SYMBOL_LENGTH);
  3666.  memcpy(vartest,var,strlen(var));
  3667.  
  3668.  switch (type) {
  3669.    case STRING_SYMTYPE: minimum_value_length = strlen((char *)val) + 1;
  3670.                         break;
  3671.    case NUMBER_SYMTYPE: minimum_value_length = 12;
  3672.                         break;
  3673.    case FLAG_SYMTYPE:   minimum_value_length = 6;
  3674.                         break;
  3675.  }
  3676.  
  3677.  sympleft  = NULL;
  3678.  sympright = NULL;
  3679.  sympref   = &bp->symtabp;
  3680.  
  3681.  while ((symp=*sympref)) {
  3682.    switch ((comp=memcmp(vartest, symp->symvar, MAX_SYMBOL_LENGTH))) {
  3683.      case 0:   /* equal   */
  3684.                NNMbsynt(np,bp,var,0,
  3685.                         "Variable being declared already exists");
  3686.                return NULL;
  3687.      case 1:   /* greater */
  3688.                sympref = &symp->right;
  3689.                continue;
  3690.      default:  /* less    */
  3691.                sympref = &symp->left;
  3692.                continue;
  3693.    }
  3694.  }
  3695.  
  3696.  /* Allocate a new symbol table entry for this new symbol and
  3697.   * add it to the tree.
  3698.   */
  3699.  
  3700.  getlen = offsetof(struct symtab, symval) + minimum_value_length;
  3701.  
  3702.  GETMAIN(sympnew, char, getlen, "new symbol table entry");
  3703.  if (!sympnew) {
  3704.    NNMbsynt(np,bp,var,0,"Not enough storage to declare symbol");
  3705.    return NULL;
  3706.  }
  3707.  
  3708.  memcpy(sympnew->symvar, vartest, MAX_SYMBOL_LENGTH);
  3709.  sympnew->left   = sympleft;
  3710.  sympnew->right  = sympright;
  3711.  sympnew->vallen = minimum_value_length;
  3712.  *sympref        = sympnew;
  3713.  
  3714.  sympnew->type = type;
  3715.  
  3716.  switch (type) {
  3717.    case STRING_SYMTYPE:
  3718.                         strcpy(sympnew->symval,(char *)val);
  3719.                         if (np->debug_file)
  3720.                            fprintf(np->debug_file,
  3721.                                    "NNMbdecl: %s set to '%s'\n",
  3722.                                    sympnew->symvar, sympnew->symval);
  3723.                         break;
  3724.    case NUMBER_SYMTYPE:
  3725.                         sympnew->symnum = (int)val;
  3726.                         if (np->debug_file)
  3727.                            fprintf(np->debug_file,
  3728.                                    "NNMbdecl: %s set to %d\n",
  3729.                                    sympnew->symvar, sympnew->symnum);
  3730.                         break;
  3731.    case FLAG_SYMTYPE:
  3732.                         sympnew->symnum = (int)val ? 1 : 0;
  3733.                         if (np->debug_file)
  3734.                            fprintf(np->debug_file,
  3735.                                    "NNMbdecl: %s set to %s\n",
  3736.                                    sympnew->symvar,
  3737.                                    sympnew->symnum ? "TRUE" : "FALSE");
  3738.                         break;
  3739.  }
  3740.  
  3741.  
  3742.  return sympnew;
  3743.  
  3744. }
  3745.  
  3746. ./   ADD NAME=NNMBFLUS,SSI=01000035
  3747.  
  3748.  /********************************************************************/
  3749.  /*                                                                  */
  3750.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  3751.  /*                                                                  */
  3752.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  3753.  /* including the implied warranties of merchantability and fitness, */
  3754.  /* are expressly denied.                                            */
  3755.  /*                                                                  */
  3756.  /* Provided this copyright notice is included, this software may    */
  3757.  /* be freely distributed and not offered for sale.                  */
  3758.  /*                                                                  */
  3759.  /* Changes or modifications may be made and used only by the maker  */
  3760.  /* of same, and not further distributed.  Such modifications should */
  3761.  /* be mailed to the author for consideration for addition to the    */
  3762.  /* software and incorporation in subsequent releases.               */
  3763.  /*                                                                  */
  3764.  /********************************************************************/
  3765.  
  3766. #pragma  csect(code,  "NN@BFLUS")
  3767. #pragma  csect(static,"NN$BFLUS")
  3768. #include "nn.h"
  3769. #include "nnbatch.h"
  3770.  
  3771. /****** Flush input line. ********************************************/
  3772.  
  3773. void
  3774. NNMbflus(np,bp)
  3775. Rstruc nncb         *np;
  3776. Rstruc batch        *bp;
  3777. {
  3778.  
  3779.  /* This routine eats tokens, ignoring them, until it sees a
  3780.     semicolon or a new line. */
  3781.  
  3782.  if (np->debug_file) {
  3783.    fprintf(np->debug_file,"Flushing rest of input line.\n");
  3784.  }
  3785.  
  3786.  bp->stop_at_newline = TRUE;
  3787.  
  3788.  for (;;) {
  3789.    if (!NNMbgtok(np,bp,TOKEN_FLUSH)) break;  /* get token */
  3790.    switch (bp->curtok.type) {
  3791.      case EOF_TOKEN:
  3792.      case EOL_TOKEN:
  3793.      case SEMI_TOKEN:  break;
  3794.      default:
  3795.                        if (np->debug_file) {
  3796.                          fprintf(np->debug_file,"Ignoring token.\n");
  3797.                        }
  3798.                        continue;
  3799.    }
  3800.    break;
  3801.  }
  3802.  
  3803.  bp->stop_at_newline = FALSE;
  3804.  
  3805.  return; 
  3806. }
  3807.  
  3808. ./   ADD NAME=NNMBGCMD,SSI=01000057
  3809.  
  3810.  /********************************************************************/
  3811.  /*                                                                  */
  3812.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  3813.  /*                                                                  */
  3814.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  3815.  /* including the implied warranties of merchantability and fitness, */
  3816.  /* are expressly denied.                                            */
  3817.  /*                                                                  */
  3818.  /* Provided this copyright notice is included, this software may    */
  3819.  /* be freely distributed and not offered for sale.                  */
  3820.  /*                                                                  */
  3821.  /* Changes or modifications may be made and used only by the maker  */
  3822.  /* of same, and not further distributed.  Such modifications should */
  3823.  /* be mailed to the author for consideration for addition to the    */
  3824.  /* software and incorporation in subsequent releases.               */
  3825.  /*                                                                  */
  3826.  /********************************************************************/
  3827.  
  3828. #pragma  csect(code,  "NN@BGCMD")
  3829. #pragma  csect(static,"NN$BGCMD")
  3830. #include "nn.h"
  3831. #include "nnbatch.h"
  3832.  
  3833. #define BATCHPARSER(X)   extern struct newscmd * \
  3834.                                      X (struct nncb *, struct batch *)
  3835.  
  3836. BATCHPARSER (NNMbphel);       /* Parse batch HELP         command     */
  3837. BATCHPARSER (NNMbpfor);       /* Parse batch FOR          command     */
  3838. BATCHPARSER (NNMbpif );       /* Parse batch IF           command     */
  3839. BATCHPARSER (NNMbpels);       /* Parse batch ELSE         command     */
  3840. BATCHPARSER (NNMbpque);       /* Parse batch QUERY        command     */
  3841. BATCHPARSER (NNMbpreg);       /* Parse batch REGISTER     command     */
  3842. BATCHPARSER (NNMbpder);       /* Parse batch DEREGISTER   command     */
  3843. BATCHPARSER (NNMbpset);       /* Parse batch SET          command     */
  3844. BATCHPARSER (NNMbpput);       /* Parse batch PUT          command     */
  3845. BATCHPARSER (NNMbpexe);       /* Parse batch EXEC         command     */
  3846. BATCHPARSER (NNMbpqui);       /* Parse batch QUIT         command     */
  3847. BATCHPARSER (NNMbpnnt);       /* Parse batch NNTP         command     */
  3848. BATCHPARSER (NNMbplis);       /* Parse batch LIST         command     */
  3849. BATCHPARSER (NNMbpmar);       /* Parse batch MARK         command     */
  3850. BATCHPARSER (NNMbpext);       /* Parse batch EXTRACT      command     */
  3851. BATCHPARSER (NNMbpvar);       /* Parse batch VARS         command     */
  3852. BATCHPARSER (NNMbpdec);       /* Parse batch DECLARE      command     */
  3853.  
  3854. /****** Get command. *************************************************/
  3855.  
  3856. CommandParser
  3857. NNMbgcmd(np,bp)
  3858. Rstruc nncb         *np;
  3859. Rstruc batch        *bp;
  3860. {
  3861.  char               *cp;
  3862.  struct token       *tp;
  3863.  CommandParser       cproc;
  3864.  Bool                command_not_gotten = FALSE;
  3865.  Bool                assumed_set        = FALSE;
  3866.  
  3867.  for (;;) {
  3868.  
  3869.    bp->stop_at_newline = FALSE;  /* read lines until token found */
  3870.  
  3871.    if (!(tp = PEEK())) {                          /* peek token */
  3872.       command_not_gotten = TRUE;
  3873.    }
  3874.    else switch (tp->type) {
  3875.      case EOF_TOKEN:
  3876.             EAT();
  3877.             return FALSE; /* OK, no more commands to process */
  3878.      case WORD_TOKEN:
  3879.             break;        /* good, what a command should look like */
  3880.      case EOL_TOKEN:
  3881.      case SEMI_TOKEN:
  3882.             EAT();
  3883.             continue;     /* keep looping */
  3884.      case STRING_TOKEN:
  3885.             EAT();
  3886.             NNMbsynt(np,bp,NULL,0,
  3887.                      "Quoted string where command name expected");
  3888.             command_not_gotten = TRUE;
  3889.             break;
  3890.      default:
  3891.             EAT();
  3892.             NNMbsynt(np,bp,tp->string,0,
  3893.                      "Invalid token where command name expected");
  3894.             command_not_gotten = TRUE;
  3895.             break;
  3896.    }
  3897.    break; /* continue only when ';' found */
  3898.  }
  3899.  
  3900.  /* Determine what the command is.  If the command is not recognized,
  3901.   * but it is the name of a declared variable, then assume it is SET
  3902.   * and don't eat the token - let SET see it.
  3903.   */
  3904.  
  3905.  if (!command_not_gotten) {
  3906.   cp = tp->string;
  3907.   if      (EQUAL(cp,"HELP"        )) cproc = NNMbphel;
  3908.   else if (EQUAL(cp,"FOR"         )) cproc = NNMbpfor;
  3909.   else if (EQUAL(cp,"IF"          )) cproc = NNMbpif ;
  3910.   else if (EQUAL(cp,"ELSE"        )) cproc = NNMbpels;
  3911.   else if (EQUAL(cp,"QUERY"       )) cproc = NNMbpque;
  3912.   else if (EQUAL(cp,"REGISTER"    )) cproc = NNMbpreg;
  3913.   else if (EQUAL(cp,"DEREGISTER"  )) cproc = NNMbpder;
  3914.   else if (EQUAL(cp,"SET"         )) cproc = NNMbpset;
  3915.   else if (EQUAL(cp,"PUT"         )) cproc = NNMbpput;
  3916.   else if (EQUAL(cp,"EXEC"        )) cproc = NNMbpexe;
  3917.   else if (EQUAL(cp,"QUIT"        )) cproc = NNMbpqui;
  3918.   else if (EQUAL(cp,"NNTP"        )) cproc = NNMbpnnt;
  3919.   else if (EQUAL(cp,"LIST"        )) cproc = NNMbplis;
  3920.   else if (EQUAL(cp,"MARK"        )) cproc = NNMbpmar;
  3921.   else if (EQUAL(cp,"EXTRACT"     )) cproc = NNMbpext;
  3922.   else if (EQUAL(cp,"VARS"        )) cproc = NNMbpvar;
  3923.   else if (EQUAL(cp,"DECLARE"     )) cproc = NNMbpdec;
  3924.   else if (EQUAL(cp,"END"         )) cproc = bp->endproc;
  3925.  
  3926.   else if (NNMbvget(np,bp,cp,NO_SYMTYPE)) { /* if declared var name */
  3927.     assumed_set = TRUE;
  3928.     cproc = NNMbpset;
  3929.   }
  3930.   else { 
  3931.     NNMbsynt(np,bp,cp,0, "Command or variable name unknown");
  3932.     command_not_gotten = TRUE;
  3933.   }
  3934.  }
  3935.  
  3936.  if (!(EQUAL(cp,"ELSE"))) bp->ifcmd = NULL; /*Disallow unmatched ELSE*/
  3937.  
  3938.  if (!assumed_set) EAT();  /* Swallow the command name if 'twas real */
  3939.  
  3940.  if (command_not_gotten) {
  3941.    fprintf(np->batch_outfile, "Rest of input line ignored.\n");
  3942.    NNMbflus(np,bp);       /* Flush rest of tokens on input line */
  3943.    return FALSE;
  3944.  }
  3945.  
  3946.  return cproc;
  3947.  
  3948. }
  3949.  
  3950. ./   ADD NAME=NNMBGDO,SSI=01000043
  3951.  
  3952.  /********************************************************************/
  3953.  /*                                                                  */
  3954.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  3955.  /*                                                                  */
  3956.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  3957.  /* including the implied warranties of merchantability and fitness, */
  3958.  /* are expressly denied.                                            */
  3959.  /*                                                                  */
  3960.  /* Provided this copyright notice is included, this software may    */
  3961.  /* be freely distributed and not offered for sale.                  */
  3962.  /*                                                                  */
  3963.  /* Changes or modifications may be made and used only by the maker  */
  3964.  /* of same, and not further distributed.  Such modifications should */
  3965.  /* be mailed to the author for consideration for addition to the    */
  3966.  /* software and incorporation in subsequent releases.               */
  3967.  /*                                                                  */
  3968.  /********************************************************************/
  3969.  
  3970. #pragma  csect(code,  "NN@BGDO ")
  3971. #pragma  csect(static,"NN$BGDO ")
  3972. #include "nn.h"
  3973. #include "nnbatch.h"
  3974.  
  3975. #define MAGIC_END_COOKIE    (void *)(1)
  3976.  
  3977. /****** Handle END command. ******************************************/
  3978.  
  3979. static struct newscmd *
  3980. handle_end(np,bp)
  3981. Rstruc nncb         *np;
  3982. Rstruc batch        *bp;
  3983. {
  3984.  
  3985.  NNMbflus(np,bp);  /* flush all tokens following END */
  3986.  
  3987.  return MAGIC_END_COOKIE;
  3988. }
  3989.  
  3990. /****** Get commands, parse them and add to command tree. ************/
  3991.  
  3992. static struct cmdtree *
  3993. get_multiple_commands(np,bp,mode)
  3994. Rstruc nncb         *np;
  3995. Rstruc batch        *bp;
  3996. enum batchmode       mode;
  3997. {
  3998.  Rstruc newscmd     *cmdp        = NULL;
  3999.  struct cmdtree     *treep       = NULL;
  4000.  struct cmdtree     *treetop     = NULL;
  4001.  struct cmdtree     *treebottom  = NULL;
  4002.  CommandParser       proc;
  4003.  CommandParser       save_endproc;
  4004.  enum batchmode      save_mode;
  4005.  Bool                bad_command = FALSE;
  4006.  Bool                end_found   = FALSE;
  4007.  
  4008.  save_mode    = bp->mode;
  4009.  bp->mode     = mode;
  4010.  
  4011.  save_endproc = bp->endproc;
  4012.  bp->endproc  = handle_end;
  4013.  
  4014.  while (!bp->eof) {
  4015.  
  4016.    proc = NNMbgcmd(np,bp);   /* Get next command */
  4017.    if (!proc) {              /* If invalid command, continue */
  4018.      bad_command = TRUE;
  4019.      continue;
  4020.    }
  4021.  
  4022.    cmdp = (proc)(np,bp);     /* Parse it returning command tree */
  4023.    if (!cmdp) {              /* If syntax error, continue */
  4024.      bad_command = TRUE;
  4025.      continue;
  4026.    }
  4027.  
  4028.    if (cmdp == MAGIC_END_COOKIE) {  /* if END seen */
  4029.      end_found = TRUE;
  4030.      break;
  4031.    }
  4032.  
  4033.    /* If a newscmd structure was returned, add it to the cmd tree. */
  4034.  
  4035.    GETMAIN(treep, struct cmdtree, 1, "DO command tree");
  4036.    if (!treep) {
  4037.      bp->input_errors++;
  4038.      bad_command = TRUE;
  4039.      continue;
  4040.    }
  4041.  
  4042.    treep->next = NULL;
  4043.    treep->cmd  = cmdp;
  4044.  
  4045.    if (treebottom == NULL) treetop = treep;
  4046.    else                    treebottom->next = treep;
  4047.    treebottom = treep;
  4048.  
  4049.  }
  4050.  
  4051.  bp->endproc = save_endproc;
  4052.  bp->mode    = save_mode;
  4053.  
  4054.  if (!end_found) {
  4055.    NNMbsynt(np,bp,NULL,0,"No END found to match DO");
  4056.  }
  4057.  
  4058.  return treetop;
  4059. }
  4060.  
  4061. /****** Get a single command, parse it and make command tree. ********/
  4062.  
  4063. static struct cmdtree *
  4064. get_single_command(np,bp,mode)
  4065. Rstruc nncb         *np;
  4066. Rstruc batch        *bp;
  4067. enum batchmode       mode;
  4068. {
  4069.  Rstruc newscmd     *cmdp        = NULL;
  4070.  struct cmdtree     *treep       = NULL;
  4071.  struct token       *tp;
  4072.  CommandParser       proc;
  4073.  enum batchmode      save_mode;
  4074.  
  4075.  save_mode    = bp->mode;
  4076.  bp->mode     = mode;
  4077.  
  4078.  if (!(tp = PEEK())) return NULL;
  4079.  
  4080.  /* Handle null command (e.g. IF x THEN; ELSE; ) */
  4081.  
  4082.  if (tp->type == SEMI_TOKEN) return NULL;
  4083.  
  4084.  proc = NNMbgcmd(np,bp);   /* Get next command */
  4085.  if (!proc) return NULL;   /* If invalid command, error */
  4086.  
  4087.  cmdp = (proc)(np,bp);     /* Parse it returning command tree */
  4088.  if (!cmdp) return NULL;   /* If syntax error, error */
  4089.  
  4090.  bp->mode = save_mode;
  4091.  
  4092.  /* If a newscmd structure was returned, add it to the cmd tree. */
  4093.  
  4094.  GETMAIN(treep, struct cmdtree, 1, "DO command tree");
  4095.  if (!treep) {
  4096.    bp->input_errors++;
  4097.    return NULL;
  4098.  }
  4099.  
  4100.  treep->next = NULL;
  4101.  treep->cmd  = cmdp;
  4102.  
  4103.  return treep;
  4104. }
  4105.  
  4106. /****** Get keyword. *************************************************/
  4107.  
  4108. static Bool
  4109. get_keyword(np,bp,key)
  4110. Rstruc nncb                 *np;
  4111. Rstruc batch                *bp;
  4112. char                        *key;
  4113. {
  4114.  struct token               *tp;
  4115.  
  4116.  if ((tp = PEEK()) && tp->type == WORD_TOKEN && EQUAL(tp->string,key)) {
  4117.    EAT();
  4118.    return TRUE;
  4119.  }
  4120.  
  4121.  else return FALSE;
  4122.  
  4123. }
  4124.  
  4125. /****** Get a DO-END command group. **********************************/
  4126.  
  4127. struct cmdtree *
  4128. NNMbgdo(np,bp,mode)
  4129. Rstruc nncb         *np;
  4130. Rstruc batch        *bp;
  4131. enum batchmode       mode;
  4132. {
  4133.  
  4134.  /* Look for DO (required).  When found, get commands until END seen.*/
  4135.  
  4136.  if (get_keyword(np,bp,"DO")) {
  4137.    NNMbtras(np,bp,"DO");
  4138.    return get_multiple_commands(np,bp,mode);
  4139.  }
  4140.  else return get_single_command(np,bp,mode);
  4141.  
  4142. }
  4143.  
  4144. ./   ADD NAME=NNMBGEXP,SSI=01000030
  4145.  
  4146.  /********************************************************************/
  4147.  /*                                                                  */
  4148.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  4149.  /*                                                                  */
  4150.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  4151.  /* including the implied warranties of merchantability and fitness, */
  4152.  /* are expressly denied.                                            */
  4153.  /*                                                                  */
  4154.  /* Provided this copyright notice is included, this software may    */
  4155.  /* be freely distributed and not offered for sale.                  */
  4156.  /*                                                                  */
  4157.  /* Changes or modifications may be made and used only by the maker  */
  4158.  /* of same, and not further distributed.  Such modifications should */
  4159.  /* be mailed to the author for consideration for addition to the    */
  4160.  /* software and incorporation in subsequent releases.               */
  4161.  /*                                                                  */
  4162.  /********************************************************************/
  4163.  
  4164. #pragma  csect(code,  "NN@BGEXP")
  4165. #pragma  csect(static,"NN$BGEXP")
  4166. #include "nn.h"
  4167. #include "nnbatch.h"
  4168.  
  4169. static Exp              get_exp();
  4170. static Choice           get_choice();
  4171. static Relation         get_relation();
  4172. static Value            get_value();
  4173. static Quantity         get_quantity();
  4174. static Term             get_term();
  4175. static Factor           get_factor();
  4176. static Unop             get_unop();
  4177. static Addop            get_addop();
  4178. static Mulop            get_mulop();
  4179. static Logop            get_logop();
  4180. static Relop            get_relop();
  4181. static Constant         get_constant();
  4182. static Variable         get_variable();
  4183. static Number           get_number();
  4184. static String           get_string();
  4185. static Flag             get_flag();
  4186.  
  4187. static Exp              make_exp();
  4188. static Choice           make_choice();
  4189. static Relation         make_relation();
  4190. static Value            make_value();
  4191. static Quantity         make_quantity();
  4192. static Term             make_term();
  4193. static Factor           make_factor();
  4194. static Unop             make_unop();
  4195. static Addop            make_addop();
  4196. static Mulop            make_mulop();
  4197. static Logop            make_logop();
  4198. static Relop            make_relop();
  4199. static Constant         make_constant();
  4200. static Variable         make_variable();
  4201. static Number           make_number();
  4202. static String           make_string();
  4203. static Flag             make_flag();
  4204.  
  4205. /*-------------------------------------------------------------------*/
  4206.  
  4207. static Bool
  4208. is_reserved(bp,var)
  4209. Rstruc batch    *bp;
  4210. char            *var;
  4211. {
  4212.  char          *cp;
  4213.  int            varlen = strlen(var);
  4214.  char           vartest[MAX_RESERVED_WORD_LENGTH];
  4215.  
  4216.  if (varlen >= MIN_RESERVED_WORD_LENGTH
  4217.   && varlen <= MAX_RESERVED_WORD_LENGTH) {
  4218.  
  4219.    memset(vartest,' ',MAX_RESERVED_WORD_LENGTH);
  4220.    memcpy(vartest,var,varlen);
  4221.  
  4222.    for (cp = bp->reserved_words; *cp != ' '; cp += 10) {
  4223.      if (memcmp(vartest,cp,MAX_RESERVED_WORD_LENGTH) == 0) {
  4224.        return TRUE;
  4225.      }
  4226.    }
  4227.  }
  4228.  return FALSE;
  4229. }
  4230.  
  4231. /*-------------------------------------------------------------------*/
  4232.  
  4233. static Flag
  4234. make_flag(np,bp,type,v)
  4235. Rstruc nncb     *np;
  4236. Rstruc batch    *bp;
  4237. enum symtype     type;
  4238. Fool             v;
  4239. {
  4240.  Flag            p;
  4241.  
  4242.  ALLOC(p,flag);
  4243.  p->s     = type;
  4244.  p->flag1 = v;
  4245.  return p;
  4246.  
  4247. }
  4248.  
  4249. /*-------------------------------------------------------------------*/
  4250.  
  4251. static String
  4252. make_string(np,bp,type,v)
  4253. Rstruc nncb     *np;
  4254. Rstruc batch    *bp;
  4255. enum symtype     type;
  4256. char            *v;
  4257. {
  4258.  String          p;
  4259.  
  4260.  ALLOC(p,string);
  4261.  p->s       = type;
  4262.  p->string1 = NNMcopy(np,v);
  4263.  return p;
  4264.  
  4265. }
  4266.  
  4267. /*-------------------------------------------------------------------*/
  4268.  
  4269. static Number
  4270. make_number(np,bp,type,v)
  4271. Rstruc nncb     *np;
  4272. Rstruc batch    *bp;
  4273. enum symtype     type;
  4274. int              v;
  4275. {
  4276.  Number          p;
  4277.  
  4278.  ALLOC(p,number);
  4279.  p->s       = type;
  4280.  p->number1 = v;
  4281.  return p;
  4282.  
  4283. }
  4284.  
  4285. /*-------------------------------------------------------------------*/
  4286.  
  4287. static Variable
  4288. make_variable(np,bp,type,v)
  4289. Rstruc nncb     *np;
  4290. Rstruc batch    *bp;
  4291. enum symtype     type;
  4292. char            *v;
  4293. {
  4294.  Variable        p;
  4295.  
  4296.  ALLOC(p,variable);
  4297.  p->s         = type;
  4298.  p->variable1 = NNMcopy(np,v);
  4299.  return p;
  4300. }
  4301.  
  4302. /*-------------------------------------------------------------------*/
  4303.  
  4304. static Relop
  4305. make_relop(np,bp,t)
  4306. Rstruc nncb     *np;
  4307. Rstruc batch    *bp;
  4308. enum optype      t;
  4309. {
  4310.  Relop           p;
  4311.  
  4312.  ALLOC(p,relop);
  4313.  p->op1 = t;
  4314.  return p;
  4315. }
  4316.  
  4317. /*-------------------------------------------------------------------*/
  4318.  
  4319. static Logop
  4320. make_logop(np,bp,t)
  4321. Rstruc nncb     *np;
  4322. Rstruc batch    *bp;
  4323. enum optype      t;
  4324. {
  4325.  Logop           p;
  4326.  
  4327.  ALLOC(p,logop);
  4328.  p->op1 = t;
  4329.  return p;
  4330. }
  4331.  
  4332. /*-------------------------------------------------------------------*/
  4333.  
  4334. static Mulop
  4335. make_mulop(np,bp,t)
  4336. Rstruc nncb     *np;
  4337. Rstruc batch    *bp;
  4338. enum optype      t;
  4339. {
  4340.  Mulop           p;
  4341.  
  4342.  ALLOC(p,mulop);
  4343.  p->op1 = t;
  4344.  return p;
  4345. }
  4346.  
  4347. /*-------------------------------------------------------------------*/
  4348.  
  4349. static Addop
  4350. make_addop(np,bp,t)
  4351. Rstruc nncb     *np;
  4352. Rstruc batch    *bp;
  4353. enum optype      t;
  4354. {
  4355.  Addop           p;
  4356.  
  4357.  ALLOC(p,addop);
  4358.  p->op1 = t;
  4359.  return p;
  4360. }
  4361.  
  4362. /*-------------------------------------------------------------------*/
  4363.  
  4364. static Unop
  4365. make_unop(np,bp,t)
  4366. Rstruc nncb     *np;
  4367. Rstruc batch    *bp;
  4368. enum optype      t;
  4369. {
  4370.  Unop            p;
  4371.  
  4372.  ALLOC(p,unop);
  4373.  p->op1 = t;
  4374.  return p;
  4375. }
  4376.  
  4377. /*-------------------------------------------------------------------*/
  4378.  
  4379. static Constant
  4380. make_constant_a(np,bp,type,p1)
  4381. Rstruc nncb     *np;
  4382. Rstruc batch    *bp;
  4383. enum symtype     type;
  4384. Number           p1;
  4385. {
  4386.  Constant        p;
  4387.  
  4388.  ALLOC(p,constant);
  4389.  p->r           = RHSTYPE_A;
  4390.  p->s           = type;
  4391.  p->u.a.number1 = p1;
  4392.  return p;
  4393. }
  4394.  
  4395. /*-------------------------------------------------------------------*/
  4396.  
  4397. static Constant
  4398. make_constant_b(np,bp,type,p1)
  4399. Rstruc nncb     *np;
  4400. Rstruc batch    *bp;
  4401. enum symtype     type;
  4402. String           p1;
  4403. {
  4404.  Constant        p;
  4405.  
  4406.  ALLOC(p,constant);
  4407.  p->r           = RHSTYPE_B;
  4408.  p->s           = type;
  4409.  p->u.b.string1 = p1;
  4410.  return p;
  4411. }
  4412.  
  4413. /*-------------------------------------------------------------------*/
  4414.  
  4415. static Constant
  4416. make_constant_c(np,bp,type,p1)
  4417. Rstruc nncb     *np;
  4418. Rstruc batch    *bp;
  4419. enum symtype     type;
  4420. Flag             p1;
  4421. {
  4422.  Constant        p;
  4423.  
  4424.  ALLOC(p,constant);
  4425.  p->r         = RHSTYPE_C;
  4426.  p->s         = type;
  4427.  p->u.c.flag1 = p1;
  4428.  return p;
  4429. }
  4430.  
  4431. /*-------------------------------------------------------------------*/
  4432.  
  4433. static Factor
  4434. make_factor_a(np,bp,type,p1)
  4435. Rstruc nncb    *np;
  4436. Rstruc batch    *bp;
  4437. enum symtype    type;
  4438. Constant        p1;
  4439. {
  4440.  Factor         p;
  4441.  
  4442.  ALLOC(p,factor);
  4443.  p->r             = RHSTYPE_A;
  4444.  p->s             = type;
  4445.  p->u.a.constant1 = p1;
  4446.  return p;
  4447. }
  4448.  
  4449. /*-------------------------------------------------------------------*/
  4450.  
  4451. static Factor
  4452. make_factor_b(np,bp,type,p1)
  4453. Rstruc nncb    *np;
  4454. Rstruc batch    *bp;
  4455. enum symtype    type;
  4456. Variable        p1;
  4457. {
  4458.  Factor         p;
  4459.  
  4460.  ALLOC(p,factor);
  4461.  p->r             = RHSTYPE_B;
  4462.  p->s             = type;
  4463.  p->u.b.variable1 = p1;
  4464.  return p;
  4465. }
  4466.  
  4467. /*-------------------------------------------------------------------*/
  4468.  
  4469. static Factor
  4470. make_factor_c(np,bp,type,p1,p2)
  4471. Rstruc nncb    *np;
  4472. Rstruc batch    *bp;
  4473. enum symtype    type;
  4474. Unop            p1;
  4475. Factor          p2;
  4476. {
  4477.  Factor         p;
  4478.  
  4479.  ALLOC(p,factor);
  4480.  p->r             = RHSTYPE_C;
  4481.  p->s             = type;
  4482.  p->u.c.unop1     = p1;
  4483.  p->u.c.factor2   = p2;
  4484.  return p;
  4485. }
  4486.  
  4487. /*-------------------------------------------------------------------*/
  4488.  
  4489. static Factor
  4490. make_factor_d(np,bp,type,p1)
  4491. Rstruc nncb    *np;
  4492. Rstruc batch    *bp;
  4493. enum symtype    type;
  4494. Exp             p1;
  4495. {
  4496.  Factor         p;
  4497.  
  4498.  ALLOC(p,factor);
  4499.  p->r        = RHSTYPE_D;
  4500.  p->s        = type;
  4501.  p->u.d.exp1 = p1;
  4502.  return p;
  4503. }
  4504.  
  4505. /*-------------------------------------------------------------------*/
  4506.  
  4507. static Term
  4508. make_term_a(np,bp,type,p1)
  4509. Rstruc nncb    *np;
  4510. Rstruc batch    *bp;
  4511. enum symtype    type;
  4512. Factor          p1;
  4513. {
  4514.  Term           p;
  4515.  
  4516.  ALLOC(p,term);
  4517.  p->r           = RHSTYPE_A;
  4518.  p->s           = type;
  4519.  p->u.a.factor1 = p1;
  4520.  return p;
  4521. }
  4522.  
  4523. /*-------------------------------------------------------------------*/
  4524.  
  4525. static Term
  4526. make_term_b(np,bp,type,p1,p2,p3)
  4527. Rstruc nncb    *np;
  4528. Rstruc batch    *bp;
  4529. enum symtype    type;
  4530. Term            p1;
  4531. Mulop           p2;
  4532. Factor          p3;
  4533. {
  4534.  Term           p;
  4535.  
  4536.  ALLOC(p,term);
  4537.  p->r           = RHSTYPE_B;
  4538.  p->s           = type;
  4539.  p->u.b.term1   = p1;
  4540.  p->u.b.mulop2  = p2;
  4541.  p->u.b.factor3 = p3;
  4542.  return p;
  4543. }
  4544.  
  4545. /*-------------------------------------------------------------------*/
  4546.  
  4547. static Quantity
  4548. make_quantity_a(np,bp,type,p1)
  4549. Rstruc nncb    *np;
  4550. Rstruc batch    *bp;
  4551. enum symtype    type;
  4552. Term            p1;
  4553. {
  4554.  Quantity       p;
  4555.  
  4556.  ALLOC(p,quantity);
  4557.  p->r           = RHSTYPE_A;
  4558.  p->s           = type;
  4559.  p->u.a.term1   = p1;
  4560.  return p;
  4561. }
  4562.  
  4563. /*-------------------------------------------------------------------*/
  4564.  
  4565. static Quantity
  4566. make_quantity_b(np,bp,type,p1,p2,p3)
  4567. Rstruc nncb    *np;
  4568. Rstruc batch    *bp;
  4569. enum symtype    type;
  4570. Quantity        p1;
  4571. Addop           p2;
  4572. Term            p3;
  4573. {
  4574.  Quantity       p;
  4575.  
  4576.  ALLOC(p,quantity);
  4577.  p->r             = RHSTYPE_B;
  4578.  p->s             = type;
  4579.  p->u.b.quantity1 = p1;
  4580.  p->u.b.addop2    = p2;
  4581.  p->u.b.term3     = p3;
  4582.  return p;
  4583. }
  4584.  
  4585. /*-------------------------------------------------------------------*/
  4586.  
  4587. static Value
  4588. make_value_a(np,bp,type,p1)
  4589. Rstruc nncb    *np;
  4590. Rstruc batch    *bp;
  4591. enum symtype    type;
  4592. Quantity        p1;
  4593. {
  4594.  Value           p;
  4595.  
  4596.  ALLOC(p,value);
  4597.  p->r             = RHSTYPE_A;
  4598.  p->s             = type;
  4599.  p->u.a.quantity1 = p1;
  4600.  return p;
  4601. }
  4602.  
  4603. /*-------------------------------------------------------------------*/
  4604.  
  4605. static Value
  4606. make_value_b(np,bp,type,p1,p2)
  4607. Rstruc nncb    *np;
  4608. Rstruc batch    *bp;
  4609. enum symtype    type;
  4610. Value           p1;
  4611. Quantity        p2;
  4612. {
  4613.  Value          p;
  4614.  
  4615.  ALLOC(p,value);
  4616.  p->r             = RHSTYPE_B;
  4617.  p->s             = type;
  4618.  p->u.b.value1    = p1;
  4619.  p->u.b.quantity2 = p2;
  4620.  return p;
  4621. }
  4622.  
  4623. /*-------------------------------------------------------------------*/
  4624.  
  4625. static Relation
  4626. make_relation_a(np,bp,type,p1)
  4627. Rstruc nncb    *np;
  4628. Rstruc batch    *bp;
  4629. enum symtype    type;
  4630. Value           p1;
  4631. {
  4632.  Relation       p;
  4633.  
  4634.  ALLOC(p,relation);
  4635.  p->r           = RHSTYPE_A;
  4636.  p->s           = type;
  4637.  p->u.a.value1  = p1;
  4638.  return p;
  4639. }
  4640.  
  4641. /*-------------------------------------------------------------------*/
  4642.  
  4643. static Relation
  4644. make_relation_b(np,bp,type,p1,p2,p3)
  4645. Rstruc nncb    *np;
  4646. Rstruc batch    *bp;
  4647. enum symtype    type;
  4648. Value           p1;
  4649. Relop           p2;
  4650. Value           p3;
  4651. {
  4652.  Relation       p;
  4653.  
  4654.  ALLOC(p,relation);
  4655.  p->r             = RHSTYPE_B;
  4656.  p->s             = type;
  4657.  p->u.b.value1    = p1;
  4658.  p->u.b.relop2    = p2;
  4659.  p->u.b.value3    = p3;
  4660.  return p;
  4661. }
  4662.  
  4663. /*-------------------------------------------------------------------*/
  4664.  
  4665. static Choice
  4666. make_choice_a(np,bp,type,p1)
  4667. Rstruc nncb    *np;
  4668. Rstruc batch    *bp;
  4669. enum symtype    type;
  4670. Relation        p1;
  4671. {
  4672.  Choice         p;
  4673.  
  4674.  ALLOC(p,choice);
  4675.  p->r             = RHSTYPE_A;
  4676.  p->s             = type;
  4677.  p->u.a.relation1 = p1;
  4678.  return p;
  4679. }
  4680.  
  4681. /*-------------------------------------------------------------------*/
  4682.  
  4683. static Choice
  4684. make_choice_b(np,bp,type,p1,p2,p3)
  4685. Rstruc nncb    *np;
  4686. Rstruc batch    *bp;
  4687. enum symtype    type;
  4688. Choice          p1;
  4689. Logop           p2;
  4690. Relation        p3;
  4691. {
  4692.  Choice         p;
  4693.  
  4694.  ALLOC(p,choice);
  4695.  p->r             = RHSTYPE_B;
  4696.  p->s             = type;
  4697.  p->u.b.choice1   = p1;
  4698.  p->u.b.logop2    = p2;
  4699.  p->u.b.relation3 = p3;
  4700.  return p;
  4701. }
  4702.  
  4703. /*-------------------------------------------------------------------*/
  4704.  
  4705. static Exp
  4706. make_exp_a(np,bp,type,p1)
  4707. Rstruc nncb    *np;
  4708. Rstruc batch    *bp;
  4709. enum symtype    type;
  4710. Choice          p1;
  4711. {
  4712.  Exp            p;
  4713.  
  4714.  ALLOC(p,exp);
  4715.  p->r           = RHSTYPE_A;
  4716.  p->s           = type;
  4717.  p->u.a.choice1 = p1;
  4718.  return p;
  4719. }
  4720.  
  4721. /*-------------------------------------------------------------------*/
  4722.  
  4723. static Exp
  4724. make_exp_b(np,bp,type,p1,p2,p3)
  4725. Rstruc nncb    *np;
  4726. Rstruc batch    *bp;
  4727. enum symtype    type;
  4728. Exp             p1;
  4729. Exp             p2;
  4730. Exp             p3;
  4731. {
  4732.  Exp            p;
  4733.  
  4734.  ALLOC(p,exp);
  4735.  p->r        = RHSTYPE_B;
  4736.  p->s        = type;
  4737.  p->u.b.exp1 = p1;
  4738.  p->u.b.exp2 = p2;
  4739.  p->u.b.exp3 = p3;
  4740.  return p;
  4741. }
  4742.  
  4743. /*===================================================================*/
  4744.  
  4745. static Flag
  4746. get_flag(np,bp)
  4747. Rstruc nncb         *np;
  4748. Rstruc batch        *bp;
  4749. {
  4750.  struct token       *tp;
  4751.  
  4752.  if (!(tp = PEEK())) LOSE;
  4753.  switch (tp->type) {
  4754.    case WORD_TOKEN:
  4755.      if (EQUAL(tp->string,"FALSE") ||
  4756.          EQUAL(tp->string,"NO"   ) ||
  4757.          EQUAL(tp->string,"OFF"  )) {
  4758.        EAT();
  4759.        return make_flag(np,bp,FLAG_SYMTYPE,FALSE);
  4760.      }
  4761.      else
  4762.      if (EQUAL(tp->string,"TRUE" ) ||
  4763.          EQUAL(tp->string,"YES"  ) ||
  4764.          EQUAL(tp->string,"ON"   )) {
  4765.        EAT();
  4766.        return make_flag(np,bp,FLAG_SYMTYPE,TRUE);
  4767.      }
  4768.    default:        return NULL;
  4769.  }
  4770. }
  4771.  
  4772. /*-------------------------------------------------------------------*/
  4773.  
  4774. static String
  4775. get_string(np,bp)
  4776. Rstruc nncb         *np;
  4777. Rstruc batch        *bp;
  4778. {
  4779.  struct token       *tp;
  4780.  
  4781.  if (!(tp = PEEK())) LOSE;
  4782.  switch (tp->type) {
  4783.    case STRING_TOKEN:
  4784.             EAT();
  4785.             return make_string(np,bp,STRING_SYMTYPE,tp->string);
  4786.    default: return NULL;
  4787.  }
  4788. }
  4789.  
  4790. /*-------------------------------------------------------------------*/
  4791.  
  4792. static Number
  4793. get_number(np,bp)
  4794. Rstruc nncb         *np;
  4795. Rstruc batch        *bp;
  4796. {
  4797.  struct token       *tp;
  4798.  
  4799.  if (!(tp = PEEK())) LOSE;
  4800.  switch (tp->type) {
  4801.    case NUMBER_TOKEN:
  4802.             EAT();
  4803.             return make_number(np,bp,NUMBER_SYMTYPE,tp->number);
  4804.    default: return NULL;
  4805.  }
  4806. }
  4807.  
  4808. /*-------------------------------------------------------------------*/
  4809.  
  4810. static Variable
  4811. get_variable(np,bp)
  4812. Rstruc nncb         *np;
  4813. Rstruc batch        *bp;
  4814. {
  4815.  struct token       *tp;
  4816.  enum symtype        type;
  4817.  
  4818.  if (!(tp = PEEK())) LOSE;
  4819.  switch (tp->type) {
  4820.    case WORD_TOKEN:
  4821.             if (is_reserved(bp,tp->string)) return NULL;
  4822.             EAT();
  4823.             type = (enum symtype)NNMbvget(np,bp,tp->string,NO_SYMTYPE);
  4824.             if (type == NO_SYMTYPE) ERR("variable not declared");
  4825.             return make_variable(np,bp,type,tp->string);
  4826.    default: return NULL;
  4827.  }
  4828. }
  4829.  
  4830. /*-------------------------------------------------------------------*/
  4831.  
  4832. static Constant
  4833. get_constant(np,bp)
  4834. Rstruc nncb         *np;
  4835. Rstruc batch        *bp;
  4836. {
  4837.  Number              a1;
  4838.  String              b1;
  4839.  Flag                c1;
  4840.  
  4841.  if ((a1 = get_number(np,bp)))
  4842.     return make_constant_a(np,bp,NUMBER_SYMTYPE,a1);
  4843.  if ((b1 = get_string(np,bp)))
  4844.     return make_constant_b(np,bp,STRING_SYMTYPE,b1);
  4845.  if ((c1 = get_flag(np,bp)))
  4846.     return make_constant_c(np,bp,FLAG_SYMTYPE,c1);
  4847.  return NULL;
  4848. }
  4849.  
  4850. /*-------------------------------------------------------------------*/
  4851.  
  4852. static Addop
  4853. get_addop(np,bp)
  4854. Rstruc nncb         *np;
  4855. Rstruc batch        *bp;
  4856. {
  4857.  struct token       *tp;
  4858.  
  4859.  if (!(tp = PEEK())) LOSE;
  4860.  switch (tp->type) {
  4861.    case PLUS_TOKEN:  EAT(); return make_addop(np,bp,ADD_OP);
  4862.    case MINUS_TOKEN: EAT(); return make_addop(np,bp,SUB_OP);
  4863.    default:          return NULL;
  4864.  }
  4865. }
  4866.  
  4867. /*-------------------------------------------------------------------*/
  4868.  
  4869. static Mulop
  4870. get_mulop(np,bp)
  4871. Rstruc nncb         *np;
  4872. Rstruc batch        *bp;
  4873. {
  4874.  struct token       *tp;
  4875.  
  4876.  if (!(tp = PEEK())) LOSE;
  4877.  switch (tp->type) {
  4878.    case TIMES_TOKEN:  EAT(); return make_mulop(np,bp,MUL_OP);
  4879.    case OVER_TOKEN:   EAT(); return make_mulop(np,bp,DIV_OP);
  4880.    default:           return NULL;
  4881.  }
  4882. }
  4883.  
  4884. /*-------------------------------------------------------------------*/
  4885.  
  4886. static Logop
  4887. get_logop(np,bp)
  4888. Rstruc nncb         *np;
  4889. Rstruc batch        *bp;
  4890. {
  4891.  struct token       *tp;
  4892.  
  4893.  if (!(tp = PEEK())) LOSE;
  4894.  switch (tp->type) {
  4895.    case AND_TOKEN:  EAT(); return make_logop(np,bp,AND_OP);
  4896.    case OR_TOKEN:   EAT(); return make_logop(np,bp,OR_OP);
  4897.    case WORD_TOKEN:
  4898.      if (EQUAL(tp->string,"AND")) {
  4899.        EAT();
  4900.        return make_logop(np,bp,AND_OP);
  4901.      }
  4902.      if (EQUAL(tp->string,"OR"))  {
  4903.        EAT();
  4904.        return make_logop(np,bp,OR_OP);
  4905.      }
  4906.      return NULL;
  4907.    default:             return NULL;
  4908.  }
  4909. }
  4910.  
  4911. /*-------------------------------------------------------------------*/
  4912.  
  4913. static Relop
  4914. get_relop(np,bp)
  4915. Rstruc nncb         *np;
  4916. Rstruc batch        *bp;
  4917. {
  4918.  struct token       *tp;
  4919.  
  4920.  if (!(tp = PEEK())) LOSE;
  4921.  switch (tp->type) {
  4922.    case EQ_TOKEN:  EAT(); return make_relop(np,bp,EQ_OP);
  4923.    case NE_TOKEN:  EAT(); return make_relop(np,bp,NE_OP);
  4924.    case GT_TOKEN:  EAT(); return make_relop(np,bp,GT_OP);
  4925.    case LT_TOKEN:  EAT(); return make_relop(np,bp,LT_OP);
  4926.    case GE_TOKEN:  EAT(); return make_relop(np,bp,GE_OP);
  4927.    case LE_TOKEN:  EAT(); return make_relop(np,bp,LE_OP);
  4928.    case WORD_TOKEN:
  4929.      if (EQUAL(tp->string,"IN")) {EAT();
  4930.                                   return make_relop(np,bp,IN_OP);}
  4931.      if (EQUAL(tp->string,"EQ")) {EAT();
  4932.                                   return make_relop(np,bp,EQ_OP);}
  4933.      if (EQUAL(tp->string,"NE")) {EAT();
  4934.                                   return make_relop(np,bp,NE_OP);}
  4935.      if (EQUAL(tp->string,"GT")) {EAT();
  4936.                                   return make_relop(np,bp,GT_OP);}
  4937.      if (EQUAL(tp->string,"LT")) {EAT();
  4938.                                   return make_relop(np,bp,LT_OP);}
  4939.      if (EQUAL(tp->string,"GE")) {EAT();
  4940.                                   return make_relop(np,bp,GE_OP);}
  4941.      if (EQUAL(tp->string,"LE")) {EAT();
  4942.                                   return make_relop(np,bp,LE_OP);}
  4943.      return NULL;
  4944.    default:       return NULL;
  4945.  }
  4946. }
  4947.  
  4948. /*-------------------------------------------------------------------*/
  4949.  
  4950. static Unop
  4951. get_unop(np,bp)
  4952. Rstruc nncb         *np;
  4953. Rstruc batch        *bp;
  4954. {
  4955.  struct token       *tp;
  4956.  
  4957.  if (!(tp = PEEK())) LOSE;
  4958.  switch (tp->type) {
  4959.    case MINUS_TOKEN: EAT(); return make_unop(np,bp,SUB_OP);
  4960.    case PLUS_TOKEN:  EAT(); return make_unop(np,bp,ADD_OP);
  4961.    case NOT_TOKEN:   EAT(); return make_unop(np,bp,NOT_OP);
  4962.    case WORD_TOKEN:
  4963.      if (EQUAL(tp->string,"NOT")) {EAT();
  4964.                                    return make_unop(np,bp,NOT_OP);}
  4965.      return NULL;
  4966.    default:          return NULL;
  4967.  }
  4968. }
  4969.  
  4970. /*-------------------------------------------------------------------*/
  4971.  
  4972. static Bool
  4973. get_word(np,bp,word)
  4974. Rstruc nncb         *np;
  4975. Rstruc batch        *bp;
  4976. char                *word;
  4977. {
  4978.  struct token       *tp;
  4979.  
  4980.  if (!(tp = PEEK())) LOSE;
  4981.  switch (tp->type) {
  4982.    case WORD_TOKEN:
  4983.                     if (EQUAL(tp->string,word)) {EAT(); return TRUE;}
  4984.                     else return FALSE;
  4985.    default:         return FALSE;
  4986.  }
  4987. }
  4988.  
  4989. /*-------------------------------------------------------------------*/
  4990.  
  4991. static Bool
  4992. get_lpar(np,bp)
  4993. Rstruc nncb         *np;
  4994. Rstruc batch        *bp;
  4995. {
  4996.  struct token       *tp;
  4997.  
  4998.  if (!(tp = PEEK())) LOSE;
  4999.  switch (tp->type) {
  5000.    case LPAR_TOKEN: EAT(); return TRUE;
  5001.    default: return FALSE;
  5002.  }
  5003. }
  5004.  
  5005. /*-------------------------------------------------------------------*/
  5006.  
  5007. static Bool
  5008. get_rpar(np,bp)
  5009. Rstruc nncb         *np;
  5010. Rstruc batch        *bp;
  5011. {
  5012.  struct token       *tp;
  5013.  
  5014.  if (!(tp = PEEK())) LOSE;
  5015.  switch (tp->type) {
  5016.    case RPAR_TOKEN: EAT(); return TRUE;
  5017.    default: return FALSE;
  5018.  }
  5019. }
  5020.  
  5021. /*-------------------------------------------------------------------*/
  5022.  
  5023. static Factor
  5024. get_factor(np,bp)
  5025. Rstruc nncb     *np;
  5026. Rstruc batch    *bp;
  5027. {
  5028.  Constant        a1;
  5029.  Variable        b1;
  5030.  Unop            c1;
  5031.  Factor          c2;
  5032.  Exp             d1;
  5033.  enum symtype    type;
  5034.  enum symtype    type2;
  5035.  
  5036.  /* a:  factor -> constant */
  5037.  
  5038.  if (a1 = get_constant(np,bp)) {
  5039.    type = a1->s;
  5040.    return make_factor_a(np,bp,type,a1);
  5041.  }
  5042.  
  5043.  /* b:  factor -> variable */
  5044.  
  5045.  if ((b1 = get_variable(np,bp))) {
  5046.    type = b1->s;
  5047.    return make_factor_b(np,bp,type,b1);
  5048.  }
  5049.  
  5050.  /* c:  factor -> unop factor */
  5051.  
  5052.  if ((c1 = get_unop(np,bp))) {
  5053.    if (!(c2 = get_factor(np,bp))) ERR("expecting factor");
  5054.    type2 = c2->s;
  5055.    switch (c1->op1) {
  5056.      case SUB_OP:
  5057.           if (type2 != NUMBER_SYMTYPE) ERR("not number expression");
  5058.           type = NUMBER_SYMTYPE;
  5059.           break;
  5060.      case ADD_OP:
  5061.           if (type2 != NUMBER_SYMTYPE) ERR("not number expression");
  5062.           type = NUMBER_SYMTYPE;
  5063.           break;
  5064.      case NOT_OP:
  5065.           if (type2 != FLAG_SYMTYPE)   ERR("not flag expression");
  5066.           type = FLAG_SYMTYPE;
  5067.           break;
  5068.    }
  5069.    return make_factor_c(np,bp,type2,c1,c2);
  5070.  }
  5071.  
  5072.  /* d:  factor -> "(" exp ")" */
  5073.  
  5074.  if (get_lpar(np,bp)) {
  5075.    if (!(d1 = get_exp(np,bp))) ERR("expecting numeric expression");
  5076.    if (!get_rpar(np,bp))       ERR("expecting right parenthesis");
  5077.    type = d1->s;
  5078.    return make_factor_d(np,bp,type,d1);
  5079.  }
  5080.  
  5081.  return NULL;
  5082.  
  5083. }
  5084.  
  5085. /*-------------------------------------------------------------------*/
  5086.  
  5087. static Term
  5088. get_term(np,bp)
  5089. Rstruc nncb     *np;
  5090. Rstruc batch    *bp;
  5091. {
  5092.  Term            p;
  5093.  Factor          a1;
  5094.  Mulop           b2;
  5095.  Factor          b3;
  5096.  enum symtype    type;
  5097.  enum symtype    type1;
  5098.  enum symtype    type3;
  5099.  
  5100.  /* a:  term -> factor */
  5101.  
  5102.  if (!(a1 = get_factor(np,bp))) return NULL;
  5103.  
  5104.  type = a1->s;
  5105.  p = make_term_a(np,bp,type,a1);
  5106.  
  5107.  /* b:  term -> term mulop factor */
  5108.  
  5109.  for (;;) {
  5110.  
  5111.    if (!(b2 = get_mulop(np,bp))) break;
  5112.    if (!(b3 = get_factor(np,bp))) ERR("expecting numeric factor");
  5113.    type1 = p->s;
  5114.    type3 = b3->s;
  5115.    if (type1!=NUMBER_SYMTYPE) ERR("operand 1 not number expression");
  5116.    if (type3!=NUMBER_SYMTYPE) ERR("operand 2 not number expression");
  5117.    type = NUMBER_SYMTYPE;
  5118.    p = make_term_b(np,bp,type,p,b2,b3);
  5119.  }
  5120.  
  5121.  return p;
  5122.  
  5123. }
  5124.  
  5125. /*-------------------------------------------------------------------*/
  5126.  
  5127. static Quantity
  5128. get_quantity(np,bp)
  5129. Rstruc nncb     *np;
  5130. Rstruc batch    *bp;
  5131. {
  5132.  Quantity        p;
  5133.  Term            a1;
  5134.  Addop           b2;
  5135.  Term            b3;
  5136.  enum symtype    type;
  5137.  enum symtype    type1;
  5138.  enum symtype    type3;
  5139.  
  5140.  /* a:  quantity -> term */
  5141.  
  5142.  if (!(a1 = get_term(np,bp))) return NULL;
  5143.  
  5144.  type = a1->s;
  5145.  p = make_quantity_a(np,bp,type,a1);
  5146.  
  5147.  /* b:  quantity -> quantity addop term */
  5148.  
  5149.  for (;;) {
  5150.  
  5151.    if (!(b2 = get_addop(np,bp))) break;
  5152.    if (!(b3 = get_term(np,bp))) ERR("expecting numeric term");
  5153.    type1 = p->s;
  5154.    type3 = b3->s;
  5155.    if (type1!=NUMBER_SYMTYPE) ERR("operand 1 not number expression");
  5156.    if (type3!=NUMBER_SYMTYPE) ERR("operand 2 not number expression");
  5157.    type = NUMBER_SYMTYPE;
  5158.    p = make_quantity_b(np,bp,type,p,b2,b3);
  5159.  }
  5160.  
  5161.  return p;
  5162.  
  5163. }
  5164.  
  5165. /*-------------------------------------------------------------------*/
  5166.  
  5167. static Value
  5168. get_value(np,bp)
  5169. Rstruc nncb     *np;
  5170. Rstruc batch    *bp;
  5171. {
  5172.  Value           p;
  5173.  Quantity        a1;
  5174.  Quantity        b2;
  5175.  enum symtype    type;
  5176.  enum symtype    type1;
  5177.  enum symtype    type2;
  5178.  
  5179.  /* a:  value -> quantity */
  5180.  
  5181.  if (!(a1 = get_quantity(np,bp))) return NULL;
  5182.  
  5183.  type = a1->s;
  5184.  p = make_value_a(np,bp,type,a1);
  5185.  
  5186.  /* b:  value -> value quantity */
  5187.  
  5188.  for (;;) {
  5189.  
  5190.    if (!(b2 = get_quantity(np,bp))) break;
  5191.    type1 = p->s;
  5192.    type2 = p->s;
  5193.    type = STRING_SYMTYPE;
  5194.    p = make_value_b(np,bp,type,p,b2);
  5195.  }
  5196.  
  5197.  return p;
  5198.  
  5199. }
  5200.  
  5201. /*-------------------------------------------------------------------*/
  5202.  
  5203. static Relation
  5204. get_relation(np,bp)
  5205. Rstruc nncb     *np;
  5206. Rstruc batch    *bp;
  5207. {
  5208.  Relation        p;
  5209.  Value           a1;
  5210.  Relop           b2;
  5211.  Value           b3;
  5212.  enum symtype    type;
  5213.  enum symtype    type1;
  5214.  enum symtype    type3;
  5215.  
  5216.  /* a:  relation -> value */
  5217.  
  5218.  if (!(a1 = get_value(np,bp))) return NULL;
  5219.  
  5220.  type = a1->s;
  5221.  p = make_relation_a(np,bp,type,a1);
  5222.  
  5223.  /* b:  relation -> value relop value */
  5224.  
  5225.  if (!(b2 = get_relop(np,bp))) return p;
  5226.  if (!(b3 = get_value(np,bp)))
  5227.     ERR("expecting string or numeric value");
  5228.  type1 = a1->s;
  5229.  type3 = b3->s;
  5230.  switch (b2->op1) {
  5231.    case IN_OP:
  5232.      if (type1 != STRING_SYMTYPE)
  5233.         ERR("operand 1 not string expression");
  5234.      if (type3 != STRING_SYMTYPE)
  5235.         ERR("operand 3 not string expression");
  5236.      break;
  5237.    case EQ_OP:
  5238.    case NE_OP:
  5239.      if (!((type1 == NUMBER_SYMTYPE && type3 == NUMBER_SYMTYPE)
  5240.         || (type1 == STRING_SYMTYPE && type3 == STRING_SYMTYPE)
  5241.         || (type1 == FLAG_SYMTYPE   && type3 == FLAG_SYMTYPE)))
  5242.       ERR("operands are not both of the same type");
  5243.      break;
  5244.    default:
  5245.      if (!((type1 == NUMBER_SYMTYPE && type3 == NUMBER_SYMTYPE)
  5246.         || (type1 == STRING_SYMTYPE && type3 == STRING_SYMTYPE)))
  5247.       ERR("operands are not both numeric or both string expressions");
  5248.      break;
  5249.  }
  5250.  type = FLAG_SYMTYPE;
  5251.  p = make_relation_b(np,bp,type,a1,b2,b3);
  5252.  
  5253.  return p;
  5254.  
  5255. }
  5256.  
  5257. /*-------------------------------------------------------------------*/
  5258.  
  5259. static Choice
  5260. get_choice(np,bp)
  5261. Rstruc nncb     *np;
  5262. Rstruc batch    *bp;
  5263. {
  5264.  Choice          p;
  5265.  Relation        a1;
  5266.  Logop           b2;
  5267.  Relation        b3;
  5268.  enum symtype    type;
  5269.  enum symtype    type1;
  5270.  enum symtype    type3;
  5271.  
  5272.  /* a:  choice -> relation */
  5273.  
  5274.  if (!(a1 = get_relation(np,bp))) return NULL;
  5275.  
  5276.  type = a1->s;
  5277.  p = make_choice_a(np,bp,type,a1);
  5278.  
  5279.  /* b:  choice -> choice logop relation */
  5280.  
  5281.  for (;;) {
  5282.  
  5283.    if (!(b2 = get_logop(np,bp))) break;
  5284.    if (!(b3 = get_relation(np,bp)))
  5285.       ERR("expecting logical expression");
  5286.    type1 = p->s;
  5287.    type3 = b3->s;
  5288.    if (type1 != FLAG_SYMTYPE) ERR("operand 1 not logical expression");
  5289.    if (type3 != FLAG_SYMTYPE) ERR("operand 2 not logical expression");
  5290.    type = FLAG_SYMTYPE;
  5291.    p = make_choice_b(np,bp,type,p,b2,b3);
  5292.  }
  5293.  
  5294.  return p;
  5295.  
  5296. }
  5297.  
  5298. /*-------------------------------------------------------------------*/
  5299.  
  5300. static Exp
  5301. get_exp(np,bp)
  5302. Rstruc nncb     *np;
  5303. Rstruc batch    *bp;
  5304. {
  5305.  Choice          a1;
  5306.  Exp             b1;
  5307.  Exp             b2;
  5308.  Exp             b3;
  5309.  enum symtype    type;
  5310.  enum symtype    type1;
  5311.  enum symtype    type2;
  5312.  enum symtype    type3;
  5313.  
  5314.  /* b:  exp -> "IF" exp "THEN" exp "ELSE" exp */
  5315.  
  5316.  if (get_word(np,bp,"IF")) {
  5317.    if (!(b1 = get_exp(np,bp)))    ERR("expecting expression");
  5318.    if (!(get_word(np,bp,"THEN"))) ERR("expecting THEN");
  5319.    if (!(b2 = get_exp(np,bp)))    ERR("expecting expression");
  5320.    if (!(get_word(np,bp,"ELSE"))) ERR("expecting ELSE");
  5321.    if (!(b3 = get_exp(np,bp)))    ERR("expecting expression");
  5322.    type1 = b1->s;
  5323.    type2 = b2->s;
  5324.    type3 = b3->s;
  5325.    if (type1 != FLAG_SYMTYPE) ERR("operand 1 not logical expression");
  5326.    type = type2;
  5327.    return make_exp_b(np,bp,type,b1,b2,b3);
  5328.  }
  5329.  
  5330.  /* a:  exp -> choice */
  5331.  
  5332.  if (!(a1 = get_choice(np,bp))) ERR("expecting IF or expression");
  5333.  type = a1->s;
  5334.  return make_exp_a(np,bp,type,a1);
  5335.  
  5336. }
  5337.  
  5338. /*-------------------------------------------------------------------*/
  5339.  
  5340. static Exp
  5341. get_strtree(np,bp)
  5342. Rstruc nncb     *np;
  5343. Rstruc batch    *bp;
  5344. {
  5345.  Exp             p;
  5346.  
  5347.  p = get_exp(np,bp);
  5348.  if (!p) {
  5349.   NNMbsynt(np,bp,NULL,0,"no expression found");
  5350.   return NULL;
  5351.  }
  5352.  
  5353.  return p;
  5354. }
  5355.  
  5356. /*-------------------------------------------------------------------*/
  5357.  
  5358. static Exp
  5359. get_numtree(np,bp)
  5360. Rstruc nncb     *np;
  5361. Rstruc batch    *bp;
  5362. {
  5363.  Exp             p;
  5364.  
  5365.  p = get_exp(np,bp);
  5366.  if (!p) {
  5367.    NNMbsynt(np,bp,NULL,0,"no expression found");
  5368.    return NULL;
  5369.  }
  5370.  switch (p->s) {
  5371.    case STRING_SYMTYPE:
  5372.         NNMbsynt(np,bp,NULL,0,"numeric expression required");
  5373.         return NULL;
  5374.    case NUMBER_SYMTYPE:
  5375.    case FLAG_SYMTYPE:
  5376.    default:             return p;
  5377.  }
  5378. }
  5379.  
  5380. /*-------------------------------------------------------------------*/
  5381.  
  5382. static Exp
  5383. get_flagtree(np,bp)
  5384. Rstruc nncb     *np;
  5385. Rstruc batch    *bp;
  5386. {
  5387.  Exp             p;
  5388.  
  5389.  p = get_exp(np,bp);
  5390.  if (!p) {
  5391.    NNMbsynt(np,bp,NULL,0,"no expression found");
  5392.    return NULL;
  5393.  }
  5394.  switch (p->s) {
  5395.    case FLAG_SYMTYPE:  return p;
  5396.    default:
  5397.             NNMbsynt(np,bp,NULL,0,"logical expression required");
  5398.             return NULL;
  5399.  }
  5400. }
  5401.  
  5402. /****** Get expression and build an expression tree. *****************/
  5403.  
  5404. struct ptree *
  5405. NNMbgexp(np,bp,type)
  5406. Rstruc nncb         *np;
  5407. Rstruc batch        *bp;
  5408. enum symtype         type;
  5409. {
  5410.  struct ptree       *treep      = NULL;
  5411.  
  5412.  /* Define return point for syntax errors during parse. */
  5413.  
  5414.  switch (setjmp(bp->jump)) {
  5415.    case ERROR_NONE:
  5416.         break;
  5417.    case ERROR_GETMAIN_FAILURE:
  5418.         NNMbsynt(np,bp,NULL,0,"Not enough memory to parse expression");
  5419.         return NULL;
  5420.    default:
  5421.         bp->syntax_error = TRUE;
  5422.         return NULL;
  5423.  }
  5424.  
  5425.  switch (type) {
  5426.    case STRING_SYMTYPE:
  5427.                         GETMAIN(treep,struct ptree,1,"string ptree");
  5428.                         if (treep) {
  5429.                           treep->type = STRING_TREETYPE;
  5430.                           treep->exp1 = get_strtree(np,bp);
  5431.                         }
  5432.                         break;
  5433.    case NUMBER_SYMTYPE:
  5434.                         GETMAIN(treep,struct ptree,1,"number ptree");
  5435.                         if (treep) {
  5436.                           treep->type = NUMBER_TREETYPE;
  5437.                           treep->exp1 = get_numtree(np,bp);
  5438.                         }
  5439.                         break;
  5440.    case FLAG_SYMTYPE:
  5441.                         GETMAIN(treep,struct ptree,1,"flag ptree");
  5442.                         if (treep) {
  5443.                           treep->type       = FLAG_TREETYPE;
  5444.                           treep->exp1 = get_flagtree(np,bp);
  5445.                         }
  5446.                         break;
  5447.    default: NNMbsynt(np,bp,NULL,0,"Invalid type passed to NNMbgexp");
  5448.             return NULL;
  5449.  }
  5450.  
  5451.  if (!treep) {
  5452.    NNMbsynt(np,bp,NULL,0,"No storage available to build expression");
  5453.    return NULL;
  5454.  }
  5455.  
  5456.  return treep;
  5457. }
  5458.  
  5459. ./   ADD NAME=NNMBGTOK,SSI=01000046
  5460.  
  5461.  /********************************************************************/
  5462.  /*                                                                  */
  5463.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  5464.  /*                                                                  */
  5465.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  5466.  /* including the implied warranties of merchantability and fitness, */
  5467.  /* are expressly denied.                                            */
  5468.  /*                                                                  */
  5469.  /* Provided this copyright notice is included, this software may    */
  5470.  /* be freely distributed and not offered for sale.                  */
  5471.  /*                                                                  */
  5472.  /* Changes or modifications may be made and used only by the maker  */
  5473.  /* of same, and not further distributed.  Such modifications should */
  5474.  /* be mailed to the author for consideration for addition to the    */
  5475.  /* software and incorporation in subsequent releases.               */
  5476.  /*                                                                  */
  5477.  /********************************************************************/
  5478.  
  5479. #pragma  csect(code,  "NN@BGTOK")
  5480. #pragma  csect(static,"NN$BGTOK")
  5481. #include "nn.h"
  5482. #include "nnbatch.h"
  5483.  
  5484. /****** Get input line. **********************************************/
  5485.  
  5486. static char *
  5487. get_input_line(np,bp)
  5488. Rstruc nncb         *np;
  5489. Rstruc batch        *bp;
  5490. {
  5491.  char               *cp;
  5492.  
  5493.  for (;;) {
  5494.    cp = fgets(bp->inline, sizeof(bp->inline), np->batch_infile);
  5495.    if (!cp) {
  5496.      if (ferror(np->batch_infile)) {
  5497.        fprintf(stderr,"\n*** Error reading batch input file ***\n");
  5498.        abort();
  5499.      }
  5500.      bp->eof = TRUE;
  5501.      return NULL;
  5502.    }
  5503.    else if ((cp=strchr(cp,'\n'))) *cp = '\0';
  5504.  
  5505.    /* Hack to allow standard entry of EOF from the terminal. */
  5506.  
  5507.    if (EQUAL(bp->inline,"/*")) {
  5508.      fprintf(np->batch_outfile, "EOF (/*) signalled in input.\n");
  5509.      bp->eof = TRUE;
  5510.      return NULL;
  5511.    }
  5512.    fprintf(np->batch_outfile, "%s\n", bp->inline);
  5513.    if (bp->inline[0] != '#') break;
  5514.  }
  5515.  return bp->inline;
  5516. }
  5517.  
  5518. /****** Show token, for debugging only. ******************************/
  5519.  
  5520. static char *
  5521. token_description(tokp)
  5522. struct token     *tokp;
  5523. {
  5524.  char            *c;
  5525.  
  5526.  switch (tokp->type) {
  5527.                      case NO_TOKEN:       c = "no token"; break;
  5528.                      case EOL_TOKEN:      c = "EOL";      break;
  5529.                      case EOF_TOKEN:      c = "EOF";      break;
  5530.                      case AND_TOKEN:      c = "AND";      break;
  5531.                      case OR_TOKEN:       c = "OR";       break;
  5532.                      case NOT_TOKEN:      c = "NOT";      break;
  5533.                      case GT_TOKEN:       c = "GT";       break;
  5534.                      case LT_TOKEN:       c = "LT";       break;
  5535.                      case EQ_TOKEN:       c = "EQ";       break;
  5536.                      case NE_TOKEN:       c = "NE";       break;
  5537.                      case GE_TOKEN:       c = "GE";       break;
  5538.                      case LE_TOKEN:       c = "LE";       break;
  5539.                      case LPAR_TOKEN:     c = "LPAR";     break;
  5540.                      case RPAR_TOKEN:     c = "RPAR";     break;
  5541.                      case PLUS_TOKEN:     c = "PLUS";     break;
  5542.                      case MINUS_TOKEN:    c = "MINUS";    break;
  5543.                      case TIMES_TOKEN:    c = "TIMES";    break;
  5544.                      case OVER_TOKEN:     c = "OVER";     break;
  5545.                      case SEMI_TOKEN:     c = "SEMI";     break;
  5546.                      case WORD_TOKEN:     c = "WORD";     break;
  5547.                      case NUMBER_TOKEN:   c = "NUMBER";   break;
  5548.                      case STRING_TOKEN:   c = "STRING";   break;
  5549.                      case ERROR_TOKEN:    c = "ERROR";    break;
  5550.                      default:             c = "?";        break;
  5551.                 }
  5552.  return c;
  5553. }
  5554.  
  5555. /****** Get token. ***************************************************/
  5556.  
  5557. static Bool
  5558. get_token(np,bp,tokp,flushing)
  5559. Rstruc nncb         *np;
  5560. Rstruc batch        *bp;
  5561. struct token        *tokp;
  5562. Fool                 flushing;
  5563. {
  5564.  char               *cp;
  5565.  char               *dp;
  5566.  char               *ep;
  5567.  int                 len;
  5568.  Bool                inquote;
  5569.  Bool                badtoken;
  5570.  
  5571.  /* If reached end of current line, get a line */
  5572.  
  5573.  do {
  5574.    while (*bp->inchar == '\0') {
  5575.      if (bp->stop_at_newline) {
  5576.        tokp->type = EOL_TOKEN;
  5577.        strcpy(tokp->string,"<**End Of Line**>");
  5578.        return TRUE;
  5579.      }
  5580.      bp->inchar = get_input_line(np,bp);
  5581.      if (bp->inchar == NULL) {
  5582.        tokp->type = EOF_TOKEN;
  5583.        strcpy(tokp->string,"<**End Of File**>");
  5584.        return TRUE;
  5585.      }
  5586.    }
  5587.    while (isspace(*bp->inchar)) bp->inchar++;
  5588.    if (*bp->inchar == '#') *bp->inchar = '\0';
  5589.  } while (*bp->inchar == '\0');
  5590.  
  5591.  memset(tokp->string, 0, sizeof(tokp->string));
  5592.  tokp->number = 0;
  5593.  bp->syntax_error = FALSE;
  5594.  badtoken = FALSE;
  5595.  
  5596.  cp = bp->inchar;
  5597.  if (isdigit(*cp)) {
  5598.    ep = cp + strspn(cp,"0123456789");
  5599.    len = ep - cp;
  5600.    bp->inchar = ep;
  5601.    if (len > 10) {
  5602.      badtoken = TRUE;
  5603.      if (flushing) tokp->type = ERROR_TOKEN;
  5604.      else NNMbsynt(np,bp,cp,len,"Number too long");
  5605.    }
  5606.    else {
  5607.      tokp->type = NUMBER_TOKEN;
  5608.      memcpy(tokp->string, cp, len);
  5609.      tokp->number = atoi(tokp->string);
  5610.    }
  5611.  }
  5612.  else if (isalpha(*cp)) {
  5613.    dp = tokp->string;
  5614.    ep = dp + sizeof(tokp->string) - 1;
  5615.    while (isalnum(*cp)) {
  5616.      if (dp > ep) {
  5617.        if (!badtoken) {
  5618.          badtoken = TRUE;
  5619.          if (flushing) tokp->type = ERROR_TOKEN;
  5620.          else NNMbsynt(np,bp,cp,ep-cp, "Word too long");
  5621.        } 
  5622.      }
  5623.      else {
  5624.        *(dp++) = toupper(*(cp++));
  5625.      }
  5626.    }
  5627.    *dp = '\0';
  5628.    bp->inchar = cp;
  5629.    tokp->type = badtoken ? ERROR_TOKEN : WORD_TOKEN;
  5630.  }
  5631.  else if (*cp == '"') {
  5632.    bp->inchar++;
  5633.    cp = bp->inchar;
  5634.    dp = tokp->string;
  5635.    ep = tokp->string + sizeof(tokp->string) - 1;
  5636.    inquote = TRUE;
  5637.    while (inquote) {
  5638.      switch (*cp) {
  5639.        case '\0': NNMbsynt(np,bp,NULL,0,"Missing end quote");
  5640.                   inquote = FALSE;
  5641.                   bp->inchar = cp;
  5642.                   break;
  5643.        case '"' : inquote = FALSE;
  5644.                   bp->inchar = cp+1;
  5645.                   break;
  5646.        case '\\': cp++;
  5647.                   /* fall through */
  5648.        default  : if (dp > ep) {
  5649.                     if (!badtoken) {
  5650.                       badtoken = TRUE;
  5651.                       if (flushing) tokp->type = ERROR_TOKEN;
  5652.                       else
  5653.                        NNMbsynt(np,bp,NULL,0,"Quoted string too long");
  5654.                     }
  5655.                   }
  5656.                   else *(dp++) = *(cp++);
  5657.                   break;
  5658.      }
  5659.    }
  5660.    *dp = '\0';
  5661.    tokp->type = badtoken ? ERROR_TOKEN : STRING_TOKEN;
  5662.  }
  5663.  else {
  5664.    switch (*cp) {
  5665.      case ';': bp->inchar++; tokp->type = SEMI_TOKEN;  break;
  5666.      case '(': bp->inchar++; tokp->type = LPAR_TOKEN;  break;
  5667.      case ')': bp->inchar++; tokp->type = RPAR_TOKEN;  break;
  5668.      case '+': bp->inchar++; tokp->type = PLUS_TOKEN;  break;
  5669.      case '-': bp->inchar++; tokp->type = MINUS_TOKEN; break;
  5670.      case '*': bp->inchar++; tokp->type = TIMES_TOKEN; break;
  5671.      case '/': bp->inchar++; tokp->type = OVER_TOKEN;  break;
  5672.      case '&': bp->inchar++; tokp->type = AND_TOKEN;   break;
  5673.      case '|': bp->inchar++; tokp->type = OR_TOKEN;    break;
  5674.      case '>': bp->inchar++;
  5675.                switch (*bp->inchar) {
  5676.                  case '=': bp->inchar++; tokp->type = GE_TOKEN; break;
  5677.                  default:                tokp->type = GT_TOKEN; break;
  5678.                }
  5679.                break;
  5680.      case '<': bp->inchar++;
  5681.                switch (*bp->inchar) {
  5682.                  case '=': bp->inchar++; tokp->type = LE_TOKEN; break;
  5683.                  case '>': bp->inchar++; tokp->type = NE_TOKEN; break;
  5684.                  default:                tokp->type = LT_TOKEN; break;
  5685.                }
  5686.                break;
  5687.      case '=': bp->inchar++;
  5688.                switch (*bp->inchar) {
  5689.                  case '=': bp->inchar++; tokp->type = EQ_TOKEN; break;
  5690.                  default:                tokp->type = EQ_TOKEN; break;
  5691.                }
  5692.                break;
  5693.      case '^':
  5694.      case '!': bp->inchar++;
  5695.                switch (*bp->inchar) {
  5696.                  case '=': bp->inchar++; tokp->type = NE_TOKEN; break;
  5697.                  case '<': bp->inchar++; tokp->type = GT_TOKEN; break;
  5698.                  case '>': bp->inchar++; tokp->type = LT_TOKEN; break;
  5699.                  default:                tokp->type = NOT_TOKEN; break;
  5700.                }
  5701.                break;
  5702.      default:  if (flushing) tokp->type = ERROR_TOKEN;
  5703.                else NNMbsynt(np,bp,cp,1,
  5704.                              "Invalid character, cannot scan");
  5705.                bp->inchar++;
  5706.                break;
  5707.    }
  5708.    memcpy(tokp->string, cp, bp->inchar - cp); /* just in case */
  5709.  }
  5710.  
  5711.  if (np->debug_file) {
  5712.    fprintf(np->debug_file,"token = %s", token_description(tokp));
  5713.    switch (tokp->type) {
  5714.      case NUMBER_TOKEN:
  5715.               fprintf(np->debug_file, "(%d,'%s')\n",
  5716.                                       tokp->number, tokp->string);
  5717.               break;
  5718.      case WORD_TOKEN:
  5719.      case STRING_TOKEN:
  5720.      default:
  5721.               fprintf(np->debug_file, "(%s)\n", tokp->string);
  5722.               break;
  5723.    }
  5724.  }
  5725.  
  5726.  return TRUE;
  5727.  
  5728. }
  5729.  
  5730. /****** Get token. ***************************************************/
  5731.  
  5732. Bool
  5733. NNMbgtok(np,bp,func)
  5734. Rstruc nncb         *np;
  5735. Rstruc batch        *bp;
  5736. enum tokenfunc       func;
  5737. {
  5738.  
  5739.  if (!bp->tokens_read) {
  5740.    bp->inchar = get_input_line(np,bp);
  5741.    bp->tokens_read = TRUE;
  5742.    if (bp->inchar == NULL) { /* no input at all? */
  5743.      bp->curtok.type = EOF_TOKEN;
  5744.      bp->nextok.type = EOF_TOKEN;
  5745.      return TRUE;
  5746.    }
  5747.  }
  5748.  if (bp->curtok.type == EOF_TOKEN) {
  5749.    NNMbsynt(np,bp,NULL,0, "Attempt to read token past end of file");
  5750.    return FALSE;
  5751.  }
  5752.  
  5753.  switch (func) {
  5754.    case TOKEN_PEEK:
  5755.                      if (bp->nextok.type == NO_TOKEN) {
  5756.                        return get_token(np,bp,&bp->nextok,FALSE);
  5757.                      }
  5758.                      else { /* token already peeked at */
  5759.                        return TRUE;
  5760.                      }
  5761.    case TOKEN_READ:
  5762.                      if (bp->nextok.type == NO_TOKEN) {
  5763.                        return get_token(np,bp,&bp->curtok,FALSE);
  5764.                      }
  5765.                      else { /* token already peeked at */
  5766.                        memcpy((char *)&bp->curtok,
  5767.                               (char *)&bp->nextok,
  5768.                               sizeof(struct token));
  5769.                        bp->nextok.type = NO_TOKEN;
  5770.                        return TRUE;
  5771.                      }
  5772.    case TOKEN_FLUSH:
  5773.                      if (bp->nextok.type == NO_TOKEN) {
  5774.                        return get_token(np,bp,&bp->curtok,TRUE);
  5775.                      }
  5776.                      else { /* token already peeked at */
  5777.                        memcpy((char *)&bp->curtok,
  5778.                               (char *)&bp->nextok,
  5779.                               sizeof(struct token));
  5780.                        bp->nextok.type = NO_TOKEN;
  5781.                        return TRUE;
  5782.                      }
  5783.  }
  5784.  
  5785. }
  5786.  
  5787. ./   ADD NAME=NNMBPDEC,SSI=01000059
  5788.  
  5789.  /********************************************************************/
  5790.  /*                                                                  */
  5791.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  5792.  /*                                                                  */
  5793.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  5794.  /* including the implied warranties of merchantability and fitness, */
  5795.  /* are expressly denied.                                            */
  5796.  /*                                                                  */
  5797.  /* Provided this copyright notice is included, this software may    */
  5798.  /* be freely distributed and not offered for sale.                  */
  5799.  /*                                                                  */
  5800.  /* Changes or modifications may be made and used only by the maker  */
  5801.  /* of same, and not further distributed.  Such modifications should */
  5802.  /* be mailed to the author for consideration for addition to the    */
  5803.  /* software and incorporation in subsequent releases.               */
  5804.  /*                                                                  */
  5805.  /********************************************************************/
  5806.  
  5807. /*=====================================================================
  5808.  *
  5809.  * Command: DECLARE
  5810.  *
  5811.  * Syntax:  DECLARE variablename {STRING | NUMBER | FLAG}
  5812.  *
  5813.  * Mode:    any
  5814.  *
  5815.  * Function: Declares a variable that can be referenced later.
  5816.  *           Its type is specified as well.  The type can be:
  5817.  *
  5818.  *           * STRING - character string
  5819.  *           * NUMBER - integer
  5820.  *           * FLAG   - 1 or 0, TRUE or FALSE, ON or OFF, YES or NO
  5821.  *
  5822.  * Note: This command is processed at parse time only.  It is not an
  5823.  *       executable command.  No matter where it appears in the input
  5824.  *       command environment, it will be processed.  The only caveat
  5825.  *       is that a variable must be referenced by DECLARE prior to
  5826.  *       any appearance of it in the input stream.
  5827.  *
  5828.  * Examples:  DECLARE FOO STRING
  5829.  *            DECLARE BAR NUMBER
  5830.  *            DECLARE BAZ FLAG
  5831.  *
  5832.  *====================================================================*/
  5833.  
  5834. #pragma  csect(code,  "NN@BPDEC")
  5835. #pragma  csect(static,"NN$BPDEC")
  5836. #include "nn.h"
  5837. #include "nnbatch.h"
  5838.  
  5839. /****** Parse batch DECLARE      command. ****************************/
  5840.  
  5841. struct newscmd *
  5842. NNMbpdec(np,bp)
  5843. Rstruc nncb         *np;
  5844. Rstruc batch        *bp;
  5845. {
  5846.  char               *var;
  5847.  enum symtype        type;
  5848.  ANYTYPE             val;
  5849.  
  5850.  /* Next token must be variable name.  */
  5851.  
  5852.  (void)NNMbgtok(np,bp,TOKEN_READ);          /* get token */
  5853.  if (bp->curtok.type != WORD_TOKEN) {
  5854.    NNMbsynt(np,bp,NULL,0, "Expected DECLARE variable name not seen");
  5855.    NNMbflus(np,bp);                         /* flush input tokens */
  5856.    return NULL;
  5857.  }
  5858.  
  5859.  var = NNMcopy(np,bp->curtok.string);
  5860.  
  5861.  /* Next token must be one of the words STRING, NUMBER or FLAG.  */
  5862.  
  5863.  (void)NNMbgtok(np,bp,TOKEN_READ);          /* get token */
  5864.  if (bp->curtok.type != WORD_TOKEN) {
  5865.    NNMbsynt(np,bp,NULL,0, "Expected DECLARE type name not seen");
  5866.    NNMbflus(np,bp);                         /* flush input tokens */
  5867.    return NULL;
  5868.  }
  5869.  
  5870.  if      (EQUAL(bp->curtok.string,"STRING")) {
  5871.    type = STRING_SYMTYPE;
  5872.    val  = (ANYTYPE)"";
  5873.  }
  5874.  else if (EQUAL(bp->curtok.string,"NUMBER")) {
  5875.    type = NUMBER_SYMTYPE;
  5876.    val  = (ANYTYPE)0;
  5877.  }
  5878.  else if (EQUAL(bp->curtok.string,"FLAG")) {
  5879.    type = FLAG_SYMTYPE;
  5880.    val  = (ANYTYPE)0;
  5881.  }
  5882.  else {
  5883.   NNMbsynt(np,bp,bp->curtok.string,0,
  5884.            "DECLARE type not one of STRING, NUMBER or FLAG");
  5885.   return NULL;
  5886.  }
  5887.  
  5888.  if (!NNMbdecl(np,bp,var,type,val)) {
  5889.   NNMbsynt(np,bp,var,0, "Declaration failed");
  5890.   return NULL;
  5891.  }
  5892.  
  5893.  return NULL;
  5894. }
  5895.  
  5896. ./   ADD NAME=NNMBPDER,SSI=01000028
  5897.  
  5898.  /********************************************************************/
  5899.  /*                                                                  */
  5900.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  5901.  /*                                                                  */
  5902.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  5903.  /* including the implied warranties of merchantability and fitness, */
  5904.  /* are expressly denied.                                            */
  5905.  /*                                                                  */
  5906.  /* Provided this copyright notice is included, this software may    */
  5907.  /* be freely distributed and not offered for sale.                  */
  5908.  /*                                                                  */
  5909.  /* Changes or modifications may be made and used only by the maker  */
  5910.  /* of same, and not further distributed.  Such modifications should */
  5911.  /* be mailed to the author for consideration for addition to the    */
  5912.  /* software and incorporation in subsequent releases.               */
  5913.  /*                                                                  */
  5914.  /********************************************************************/
  5915.  
  5916. /*=====================================================================
  5917.  *
  5918.  * Command: DEREGISTER
  5919.  *
  5920.  * Syntax:  DEREGISTER
  5921.  *
  5922.  * Mode:    per_newsgroup
  5923.  *
  5924.  * Function: Deregisters the current newsgroup.
  5925.  *
  5926.  * Note: Arguments are not permitted.  If they are given, the
  5927.  *       function will not be performed.
  5928.  *
  5929.  * Examples:  DEREGISTER
  5930.  *
  5931.  *====================================================================*/
  5932.  
  5933. #pragma  csect(code,  "NN@BPDER")
  5934. #pragma  csect(static,"NN$BPDER")
  5935. #include "nn.h"
  5936. #include "nnbatch.h"
  5937.  
  5938. /****** Execute batch DEREGISTER command. ****************************/
  5939.  
  5940. static void
  5941. NNMbxder(np,bp,cmdp)
  5942. Rstruc nncb         *np;
  5943. Rstruc batch        *bp;
  5944. Rstruc newscmd      *cmdp;
  5945. {
  5946.  Rstruc newsgroup   *gp = bp->gp;
  5947.  
  5948.  gp->registered = 0;
  5949.  fprintf(np->batch_outfile,"Newsgroup %s deregistered.\n",gp->name);
  5950.  NNMsave(np,NULL);    /* Checkpoint NEWSRC file */
  5951.  return; 
  5952.  
  5953. }
  5954.  
  5955. /****** Parse batch DEREGISTER command. ****************************/
  5956.  
  5957. struct newscmd *
  5958. NNMbpder(np,bp)
  5959. Rstruc nncb         *np;
  5960. Rstruc batch        *bp;
  5961. {
  5962.  struct newscmd     *cmdp;
  5963.  
  5964.  bp->stop_at_newline = TRUE;
  5965.  NNMbtras(np,bp,"DEREGISTER");   /* Trash extraneous parameters */
  5966.  if (bp->syntax_error) return NULL;
  5967.  if (bp->mode != PER_NEWSGROUP_MODE) {
  5968.    NNMbsynt(np,bp,NULL,0,
  5969.             "DEREGISTER is invalid outside of per-newsgroup mode");
  5970.    return NULL;
  5971.  }
  5972.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for DEREGISTER command");
  5973.  if (cmdp) {
  5974.    cmdp->mode = PER_NEWSGROUP_MODE;
  5975.    cmdp->proc = NNMbxder;
  5976.  }
  5977.  return cmdp;
  5978. }
  5979.  
  5980. ./   ADD NAME=NNMBPELS,SSI=01000023
  5981.  
  5982.  /********************************************************************/
  5983.  /*                                                                  */
  5984.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  5985.  /*                                                                  */
  5986.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  5987.  /* including the implied warranties of merchantability and fitness, */
  5988.  /* are expressly denied.                                            */
  5989.  /*                                                                  */
  5990.  /* Provided this copyright notice is included, this software may    */
  5991.  /* be freely distributed and not offered for sale.                  */
  5992.  /*                                                                  */
  5993.  /* Changes or modifications may be made and used only by the maker  */
  5994.  /* of same, and not further distributed.  Such modifications should */
  5995.  /* be mailed to the author for consideration for addition to the    */
  5996.  /* software and incorporation in subsequent releases.               */
  5997.  /*                                                                  */
  5998.  /********************************************************************/
  5999.  
  6000. #pragma  csect(code,  "NN@BPELS")
  6001. #pragma  csect(static,"NN$BPELS")
  6002. #include "nn.h"
  6003. #include "nnbatch.h"
  6004.  
  6005. /****** Parse batch ELSE         command. ****************************/
  6006.  
  6007. struct newscmd *
  6008. NNMbpels(np,bp)
  6009. Rstruc nncb         *np;
  6010. Rstruc batch        *bp;
  6011. {
  6012.  struct newscmd             *cmdp       = NULL;
  6013.  struct cmdtree             *elsecmds   = NULL;
  6014.  
  6015.  cmdp = bp->ifcmd;
  6016.  bp->ifcmd = NULL;
  6017.  
  6018.  if (!cmdp) {
  6019.    NNMbsynt(np,bp,NULL,0,"ELSE without matching IF found");
  6020.  }
  6021.  
  6022.  /* Get DO-END command group.  */
  6023.  
  6024.  elsecmds = NNMbgdo(np,bp,bp->mode);
  6025.  
  6026.  if (bp->syntax_error) return NULL;
  6027.  
  6028.  if (cmdp) cmdp->cmd.fcmd.elsecmds = elsecmds;
  6029.  
  6030.  return NULL;  /* cmdp was already returned by IF */
  6031.  
  6032. }
  6033.  
  6034. ./   ADD NAME=NNMBPEXE,SSI=01000051
  6035.  
  6036.  /********************************************************************/
  6037.  /*                                                                  */
  6038.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  6039.  /*                                                                  */
  6040.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  6041.  /* including the implied warranties of merchantability and fitness, */
  6042.  /* are expressly denied.                                            */
  6043.  /*                                                                  */
  6044.  /* Provided this copyright notice is included, this software may    */
  6045.  /* be freely distributed and not offered for sale.                  */
  6046.  /*                                                                  */
  6047.  /* Changes or modifications may be made and used only by the maker  */
  6048.  /* of same, and not further distributed.  Such modifications should */
  6049.  /* be mailed to the author for consideration for addition to the    */
  6050.  /* software and incorporation in subsequent releases.               */
  6051.  /*                                                                  */
  6052.  /********************************************************************/
  6053.  
  6054. /*=====================================================================
  6055.  *
  6056.  * Command: EXEC
  6057.  *
  6058.  * Syntax:  EXEC {datum}* ;
  6059.  *
  6060.  * Mode:    any (but see note)
  6061.  *
  6062.  * Function: Executes the TSO command built from the specified
  6063.  *           data items.  Items can be:
  6064.  *
  6065.  *           * text strings
  6066.  *           * integers
  6067.  *           * words representing variables that have values
  6068.  *
  6069.  * Note: When words are used, the values they represent must be
  6070.  *       valid for the mode in which the EXEC is executed.
  6071.  *
  6072.  * Note: Since the command can span input lines and the number of
  6073.  *       arguments is variable, the arguments MUST be terminated
  6074.  *       by a semicolon or end of file.
  6075.  *
  6076.  * Examples:  EXEC "time";
  6077.  *            EXEC "SE 'I have " UNREAD " new items' USER(JRL)";
  6078.  *
  6079.  *====================================================================*/
  6080.  
  6081. #pragma  csect(code,  "NN@BPEXE")
  6082. #pragma  csect(static,"NN$BPEXE")
  6083. #include "nn.h"
  6084. #include "nnbatch.h"
  6085.  
  6086. /****** Execute batch EXEC       command. ****************************/
  6087.  
  6088. static void
  6089. NNMbxexe(np,bp,cmdp)
  6090. Rstruc nncb         *np;
  6091. Rstruc batch        *bp;
  6092. Rstruc newscmd      *cmdp;
  6093. {
  6094.  char               *string;
  6095.  int                 rc;
  6096.  
  6097.  string = NNMbbexp(np,bp,cmdp->cmd.mcmd.ptreep,STRING_SYMTYPE);
  6098.  if (bp->runtime_error) {
  6099.    fprintf(np->batch_outfile,
  6100.            "Command not executed due to errors building argument\n");
  6101.  }
  6102.  else {
  6103.    fprintf(np->batch_outfile, "Executing command:\n%s\n\n", string);
  6104.    rc = NNMtso(string);
  6105.    fprintf(np->batch_outfile, "\nReturn code: %d\n",rc);
  6106.  }
  6107.  
  6108.  return; 
  6109. }
  6110.  
  6111. /****** Parse batch EXEC         command. ****************************/
  6112.  
  6113. struct newscmd *
  6114. NNMbpexe(np,bp)
  6115. Rstruc nncb         *np;
  6116. Rstruc batch        *bp;
  6117. {
  6118.  struct newscmd     *cmdp       = NULL;
  6119.  struct ptree       *treep      = NULL;
  6120.  
  6121.  treep = NNMbgexp(np,bp,STRING_SYMTYPE); /* Get data string struct */
  6122.  
  6123.  if (!treep) {
  6124.    NNMbsynt(np,bp,NULL,0,"Error in arguments to EXEC");
  6125.    return NULL;
  6126.  }
  6127.  
  6128.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for EXEC command");
  6129.  
  6130.  if (cmdp) {
  6131.    cmdp->mode = ANY_MODE;
  6132.    cmdp->proc = NNMbxexe;
  6133.    cmdp->cmd.mcmd.ptreep = treep;
  6134.  }
  6135.  
  6136.  return cmdp;
  6137. }
  6138.  
  6139. ./   ADD NAME=NNMBPEXT,SSI=010E0051
  6140.  
  6141.  /********************************************************************/
  6142.  /*                                                                  */
  6143.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  6144.  /*                                                                  */
  6145.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  6146.  /* including the implied warranties of merchantability and fitness, */
  6147.  /* are expressly denied.                                            */
  6148.  /*                                                                  */
  6149.  /* Provided this copyright notice is included, this software may    */
  6150.  /* be freely distributed and not offered for sale.                  */
  6151.  /*                                                                  */
  6152.  /* Changes or modifications may be made and used only by the maker  */
  6153.  /* of same, and not further distributed.  Such modifications should */
  6154.  /* be mailed to the author for consideration for addition to the    */
  6155.  /* software and incorporation in subsequent releases.               */
  6156.  /*                                                                  */
  6157.  /********************************************************************/
  6158.  
  6159. /*=====================================================================
  6160.  *
  6161.  * Command: EXTRACT
  6162.  *
  6163.  * Syntax:  In per-newsgroup mode: EXTRACT ALL / READ / UNREAD
  6164.  *          In per-article   mode: EXTRACT
  6165.  *
  6166.  * Mode:    per-newsgroup or per-article
  6167.  *
  6168.  * Function: EXTRACTs all, read, or unread articles in the current
  6169.  *           newsgroup; extracts the current article.
  6170.  *
  6171.  * Note:     The file into which the article(s) are extracted is
  6172.  *           specified by the contents of file DD:NNEXTTAB, which
  6173.  *           is a listing of newsgroups and filenames.  The filenames
  6174.  *           are expected to contain a wildcard asterisk, which is
  6175.  *           substituted with the article number.
  6176.  *
  6177.  * Examples:  EXTRACT
  6178.  *            EXTRACT ALL
  6179.  *            EXTRACT READ
  6180.  *            EXTRACT UNREAD
  6181.  *
  6182.  *====================================================================*/
  6183.  
  6184. #pragma  csect(code,  "NN@BPEXT")
  6185. #pragma  csect(static,"NN$BPEXT")
  6186. #include "nn.h"
  6187. #include "nnbatch.h"
  6188.  
  6189. /********** Extract this article. ************************************/
  6190.  
  6191. static int
  6192. extract_this_article(np,bp,gp,vp)
  6193. Rstruc nncb            *np;
  6194. Rstruc batch           *bp;
  6195. Rstruc newsgroup       *gp;
  6196. VARK                   *vp;
  6197. {
  6198.  Rstruc newsarticle    *ap;
  6199.  FILE                  *xfp;
  6200.  char                  *cp1;
  6201.  char                  *cp2;
  6202.  char                   ddname  [9];
  6203.  char                   exdsn  [81];
  6204.  char                   expds  [81];
  6205.  char                   member [81];
  6206.  char                   thing_to_open [81];
  6207.  Bool                   automark;
  6208.  
  6209.  ap = VARK2PARTICLE(*vp);
  6210.  
  6211.  *member = '\0';
  6212.  *ddname = '\0';
  6213.  
  6214.  if (*bp->extractds_member) {
  6215.  
  6216.    sprintf(member,"%8.8d",ap->number);
  6217.    for (cp1=member,   cp2=bp->extractds_member;
  6218.        *cp1=='0'  && *cp2;
  6219.         cp1++,        cp2++) {
  6220.      *cp1 = *cp2;
  6221.    }
  6222.  
  6223.    sprintf(exdsn, "%s%s%s", bp->extractds_part1, member,
  6224.                             bp->extractds_part2);
  6225.  }
  6226.  else strcpy(exdsn,bp->extractds);
  6227.  
  6228.  automark = GETB("AUTOMARK");
  6229.  
  6230.  np->extract_tab_expanding          = GETB("TABEXPAND");
  6231.  np->extract_appending              = bp->extractds_mode == PDS
  6232.                                       ? FALSE
  6233.                                       : GETB("APPEND");
  6234.  np->extract_blank_before_separator = GETB("BLANKSEP");
  6235.  np->extract_separator_line         = GETC("SEPARATOR");
  6236.  np->extract_write_error            = FALSE;
  6237.  np->extract_close_error            = FALSE;
  6238.  
  6239.  /* Preallocate the data set so that we don't run out of space
  6240.   * and so that brain-damaged C/370 doesn't barf on hyphens.
  6241.   * If it already exists, use the existing one.
  6242.   */
  6243.  
  6244.  if (bp->extractds_mode == PDS) {
  6245.  
  6246.    strcpy(expds,exdsn);
  6247.    cp1 = strchr(expds,'(');
  6248.    *cp1 = '\0';
  6249.    cp2 = strchr(cp1+1,')');
  6250.    *cp2 = '\0';
  6251.  
  6252.    strcpy(member,cp1+1);
  6253.  
  6254.    if (!NNMalloc(expds,ddname,PDS,gp->article_count)) {
  6255.      fprintf(np->batch_outfile,
  6256.              "Could not allocate %s for extract.\n",expds);
  6257.      bp->runtime_error = TRUE;
  6258.      return 0;
  6259.    }
  6260.  
  6261.    sprintf(thing_to_open, "dd:%s(%s)", ddname, member);
  6262.    sprintf(exdsn, "%s(%s)", expds, member);
  6263.  
  6264.  }
  6265.  else {
  6266.    if (!NNMalloc(exdsn,ddname,SEQ,gp->article_count)) {
  6267.      fprintf(np->batch_outfile,
  6268.              "Could not allocate %s for extract.\n",exdsn);
  6269.      bp->runtime_error = TRUE;
  6270.      return 0;
  6271.    }
  6272.  
  6273.    sprintf(thing_to_open, "dd:%s", ddname);
  6274.  
  6275.  }
  6276.  
  6277.  xfp = OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(thing_to_open,
  6278.                                           np->extract_appending);
  6279.  
  6280.  if (!xfp) {
  6281.    perror(exdsn);
  6282.    fprintf(np->batch_outfile,"Could not open %s for extract.\n",exdsn);
  6283.    bp->runtime_error = TRUE;
  6284.    return 0;
  6285.  }
  6286.  
  6287.  if (!NNMpick(np,ap)) {             /* Pick article */
  6288.    fprintf(np->batch_outfile,
  6289.            "Error accessing article %d of %s.\n",ap->number,gp->name);
  6290.    fprintf(np->batch_outfile,
  6291.            "Extraction into %s was not done.\n",exdsn);
  6292.    bp->runtime_error = TRUE;
  6293.  }
  6294.  else {
  6295.    NNMbtext(np,&ap->thdr,xfp);      /* Print text   */
  6296.  }
  6297.  
  6298.  if (fclose(xfp) < 0) {
  6299.    fprintf(np->batch_outfile,
  6300.            "Error closing %s.\n", exdsn);
  6301.    bp->runtime_error = TRUE;
  6302.  }
  6303.  
  6304.  (void)NNMunalc(ddname);
  6305.  
  6306.  if (bp->runtime_error ||
  6307.      np->extract_write_error || np->extract_close_error) {
  6308.    fprintf(np->batch_outfile,
  6309.            "Error extracting article %d of %s into %s.\n",
  6310.            ap->number, gp->name, exdsn);
  6311.    bp->runtime_error = TRUE;
  6312.  }
  6313.  else {
  6314.    if (automark && IsUnread(*vp)) {
  6315.      NNMmarr(np,gp,vp);
  6316.      fprintf(np->batch_outfile,
  6317.              "Article %d of %s extracted into %s and marked read.\n",
  6318.              ap->number, gp->name, exdsn);
  6319.      NNMsave(np,NULL);   /* Checkpoint NEWSRC file */
  6320.    }
  6321.    else {
  6322.      fprintf(np->batch_outfile,
  6323.              "Article %d of %s extracted into %s.\n",
  6324.              ap->number, gp->name, exdsn);
  6325.    }
  6326.  }
  6327.  
  6328.  return (bp->runtime_error ? 0 : 1);
  6329. }
  6330.  
  6331. /********** Extract articles. ****************************************/
  6332.  
  6333. static int
  6334. extract_articles(np,bp,gp,extracting)
  6335. Rstruc nncb            *np;
  6336. Rstruc batch           *bp;
  6337. Rstruc newsgroup       *gp;
  6338. enum extracting_mode    extracting;
  6339. {
  6340.  VARK                  *vp;
  6341.  VARK                  *vpfirst;
  6342.  VARK                  *vplast;
  6343.  int                    count;
  6344.  
  6345.  np->current_newsgroup   = gp;
  6346.  np->newsgroup_selected  = FALSE;
  6347.  np->show_all_articles   = TRUE;
  6348.  
  6349.  if (!GroupSelected(gp)) gp = NNMdng(np,gp,NULL);
  6350.  if (!gp) return 0;
  6351.  
  6352.  bp->gp = gp;
  6353.  count = 0;
  6354.  if (gp->article_vector) {
  6355.    vpfirst = &GETVARKFIRST(gp);
  6356.    vplast  = &GETVARKLAST(gp);
  6357.    for (vp = vpfirst; vp <= vplast; vp++) {
  6358.      int Number = VARK2NUMBER(gp,vp);
  6359.      if ((extracting == EXTRACTING_ALL)
  6360.       || (extracting == EXTRACTING_READ   && IsRead(*vp))
  6361.       || (extracting == EXTRACTING_UNREAD && IsUnread(*vp))) {
  6362.        if (NNMrarh(np,gp,vp,0,NULL)) { /* retrieve article hdr */
  6363.          count += extract_this_article(np,bp,gp,vp);
  6364.        } 
  6365.      }
  6366.    }
  6367.  }
  6368.  
  6369.  return count;
  6370. }
  6371.  
  6372. /********** Get extract file. ****************************************/
  6373.  
  6374. static Bool
  6375. get_extract_file(np,bp,gp)
  6376. Rstruc nncb            *np;
  6377. Rstruc batch           *bp;
  6378. Rstruc newsgroup       *gp;
  6379. {
  6380.  FILE                  *tabfp;
  6381.  char                  *asp;
  6382.  char                  *cp;
  6383.  char                  *cp1;
  6384.  char                  *cp2;
  6385.  char                  *lp;
  6386.  char                  *rp;
  6387.  int                    len;
  6388.  enum data_set_type     mode;
  6389.  Bool                   found_extract;
  6390.  char                   line    [260];
  6391.  char                   tabname [260];
  6392.  char                   tabds   [260];
  6393.  
  6394.  strcpy(bp->extractds,"");
  6395.  
  6396.  /* Open the extract table. */
  6397.  
  6398.  if (!(tabfp = fopen("DD:NNEXTTAB","r"))) {
  6399.    perror("extract table (ddname NNEXTTAB)");
  6400.    fprintf(np->batch_outfile,"Could not open extract table.\n");
  6401.    bp->runtime_error = TRUE;
  6402.    return FALSE;
  6403.  }
  6404.  
  6405.  /* Search the extract table for a line that matches this newsgroup. */
  6406.  
  6407.  found_extract = FALSE;
  6408.  
  6409.  do {
  6410.    fgets(line, sizeof line, tabfp);
  6411.    if (feof(tabfp)) break;
  6412.    if (ferror(tabfp)) {
  6413.      fprintf(np->batch_outfile,
  6414.              "Error reading extract table (ddname NNEXTTAB)");
  6415.      break;
  6416.    }
  6417.    strcpy(tabname,"");
  6418.    strcpy(tabds  ,"");
  6419.    sscanf(line,"%s %s",tabname, tabds);
  6420.    if (!*tabname) continue;
  6421.    lowercase_in_place(tabname);
  6422.    if (UNEQUAL(tabname, gp->name)) continue;
  6423.    found_extract = TRUE;
  6424.    if (!*tabds) {
  6425.      fprintf(np->batch_outfile,
  6426.      "Extract table entry for group %s has no file name specified.\n",
  6427.              gp->name);
  6428.      break;
  6429.    }
  6430.  } while (!found_extract);
  6431.  
  6432.  if (!found_extract) {
  6433.    fprintf(np->batch_outfile,
  6434.     "Extract terminated for group %s, no entry in extract table.\n",
  6435.      gp->name);
  6436.    return FALSE;
  6437.  }
  6438.  
  6439.  if (fclose(tabfp) < 0) {
  6440.    fprintf(stderr,"Error closing extract table (ddname NNEXTTAB)");
  6441.    fprintf(np->batch_outfile,"Could not close extract table\n");
  6442.    bp->runtime_error = TRUE;
  6443.    return FALSE;
  6444.  }
  6445.  
  6446.  if (*tabds == '!') {
  6447.    fprintf(np->batch_outfile,
  6448.            "Extract suppressed for group %s ('!' in extract table).\n",
  6449.            gp->name);
  6450.    return FALSE;
  6451.  }
  6452.  
  6453.  /* Copy table dsn to extract dsn, upcasing and stripping all quotes */
  6454.  
  6455.  for (cp1 = tabds, cp2 = bp->extractds; *cp1; cp1++) {
  6456.    if (*cp1 != '\'') *cp2++ = toupper(*cp1);
  6457.  }
  6458.  *cp2 = '\0';
  6459.  
  6460.  lp  = strchr(bp->extractds,'(');
  6461.  rp  = strchr(bp->extractds,')');
  6462.  asp = strchr(bp->extractds,'*');
  6463.  
  6464.  if (lp && rp) {
  6465.    if (*(rp+1) != '\0') {
  6466.      fprintf(np->batch_outfile,
  6467.              "Misuse of parentheses in extract file template %s\n",
  6468.              bp->extractds);
  6469.      bp->runtime_error = TRUE;
  6470.      return FALSE;
  6471.    }
  6472.    if (!asp) {
  6473.      fprintf(np->batch_outfile,
  6474.              "Parentheses without '*' in extract file template %s\n",
  6475.              bp->extractds);
  6476.      fprintf(np->batch_outfile,
  6477.              "(cannot append multiple articles to same PDS member)\n");
  6478.      bp->runtime_error = TRUE;
  6479.      return FALSE;
  6480.    }
  6481.    mode = PDS;
  6482.  }
  6483.  else {
  6484.    if (lp || rp) {
  6485.      fprintf(np->batch_outfile,
  6486.              "Misuse of parentheses in extract file template %s\n",
  6487.              bp->extractds);
  6488.      bp->runtime_error = TRUE;
  6489.      return FALSE;
  6490.    }
  6491.    mode = SEQ;
  6492.  }
  6493.  
  6494.  if (strchr(asp+1,'*')) {
  6495.    fprintf(np->batch_outfile,
  6496.            "Too many '*' in extract file template %s\n",
  6497.            bp->extractds);
  6498.    bp->runtime_error = TRUE;
  6499.    return FALSE;
  6500.  }
  6501.  
  6502.  if (asp) {
  6503.    switch (*(asp+1)) {
  6504.      case '\0':
  6505.      case ')':
  6506.      case '(':
  6507.      case '.':  break;
  6508.      default:
  6509.             fprintf(np->batch_outfile,
  6510.                     "Invalid use of '*' in extract file template %s\n",
  6511.                     bp->extractds);
  6512.             fprintf(np->batch_outfile,
  6513.                     "(must be followed by '.', ')' or end of name)\n");
  6514.             bp->runtime_error = TRUE;
  6515.             return FALSE;
  6516.    }
  6517.    for (cp = asp-1;
  6518.         cp >= bp->extractds && (*cp != '(' && *cp != '.');
  6519.         cp--);
  6520.    cp++; 
  6521.    if (cp == asp) {
  6522.      fprintf(np->batch_outfile,
  6523.              "Invalid use of '*' in extract file template %s\n",
  6524.              bp->extractds);
  6525.      fprintf(np->batch_outfile,
  6526.              "(must be preceded by an alphanumeric dsname char)\n");
  6527.      bp->runtime_error = TRUE;
  6528.      return FALSE;
  6529.    }
  6530.    len = cp - bp->extractds;
  6531.    memcpy(bp->extractds_part1,  bp->extractds, len);
  6532.    *(bp->extractds_part1 + len) = '\0';
  6533.    len = asp - cp;
  6534.    memcpy(bp->extractds_member, cp, len);
  6535.    *(bp->extractds_member + len) = '\0';
  6536.    strcpy(bp->extractds_part2,  asp+1);
  6537.  }
  6538.  else {
  6539.    strcpy(bp->extractds_part1, bp->extractds);
  6540.    strcpy(bp->extractds_part2, "");
  6541.    strcpy(bp->extractds_member,"");
  6542.  }
  6543.  
  6544.  bp->extractds_mode = mode;
  6545.  
  6546.  return TRUE;
  6547. }
  6548.  
  6549. /********** Execute batch EXTRACT command. ***************************/
  6550.  
  6551. static void
  6552. NNMbxext(np,bp,cmdp)
  6553. Rstruc nncb            *np;
  6554. Rstruc batch           *bp;
  6555. Rstruc newscmd         *cmdp;
  6556. {
  6557.  struct newsgroup      *gp    = bp->gp;
  6558.  int                    count = 0;
  6559.  enum extracting_mode   extracting;
  6560.  
  6561.  extracting = cmdp->cmd.xcmd.extracting;
  6562.  
  6563.  if (get_extract_file(np,bp,gp)) {
  6564.    if (extracting == NO_EXTRACTING_MODE) {
  6565.      count = extract_this_article(np,bp,gp,bp->vp);
  6566.    }
  6567.    else {
  6568.      count = extract_articles(np,bp,gp,extracting);
  6569.    }
  6570.  }
  6571.  if (bp->runtime_error) {
  6572.    fprintf(np->batch_outfile, "Extraction failed for %s.\n",
  6573.                               gp->name);
  6574.  }
  6575.  else {
  6576.    fprintf(np->batch_outfile, "%d article%s extracted for %s.\n",
  6577.                               count, count==1 ? "" : "s", gp->name);
  6578.  }
  6579.  
  6580.  return; 
  6581.  
  6582. }
  6583.  
  6584. /****** Per-newsgroup mode EXTRACT. **********************************/
  6585.  
  6586. static struct newscmd *
  6587. parse_newsgroup_extract(np,bp)
  6588. Rstruc nncb            *np;
  6589. Rstruc batch           *bp;
  6590. {
  6591.  struct newscmd        *cmdp       = NULL;
  6592.  enum extracting_mode   extracting = NO_EXTRACTING_MODE;
  6593.  
  6594.  /*
  6595.   * Next token must be ALL, READ or UNREAD.
  6596.   */
  6597.  
  6598.  if (NNMbgtok(np,bp,TOKEN_READ)) {  /* get token */
  6599.    switch (bp->curtok.type) {
  6600.      case WORD_TOKEN:
  6601.                       if (EQUAL(bp->curtok.string,"ALL")) {
  6602.                         extracting = EXTRACTING_ALL;
  6603.                       }
  6604.                       if (EQUAL(bp->curtok.string,"READ")) {
  6605.                         extracting = EXTRACTING_READ;
  6606.                       }
  6607.                       else if (EQUAL(bp->curtok.string,"UNREAD")) {
  6608.                         extracting = EXTRACTING_UNREAD;
  6609.                       }
  6610.                       break;
  6611.      default:
  6612.                       break;
  6613.    }
  6614.  }
  6615.  
  6616.  if (extracting == NO_EXTRACTING_MODE) {
  6617.    NNMbsynt(np,bp,bp->curtok.string,0,
  6618.          "EXTRACT in per-newsgroup mode requires ALL, READ or UNREAD");
  6619.  }
  6620.  
  6621.  bp->stop_at_newline = TRUE;
  6622.  
  6623.  NNMbtras(np,bp,"EXTRACT"); /* Trash extraneous parameters */
  6624.  
  6625.  if (bp->syntax_error) return NULL;
  6626.  
  6627.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for EXTRACT command");
  6628.  
  6629.  if (cmdp) {
  6630.    cmdp->mode = PER_NEWSGROUP_MODE;
  6631.    cmdp->proc = NNMbxext;
  6632.    cmdp->cmd.xcmd.extracting = extracting;
  6633.  }
  6634.  
  6635.  return cmdp;
  6636. }
  6637.  
  6638. /****** Per-article mode EXTRACT. ************************************/
  6639.  
  6640. static struct newscmd *
  6641. parse_article_extract(np,bp)
  6642. Rstruc nncb            *np;
  6643. Rstruc batch           *bp;
  6644. {
  6645.  struct newscmd        *cmdp       = NULL;
  6646.  bp->stop_at_newline = TRUE;
  6647.  
  6648.  NNMbtras(np,bp,"EXTRACT"); /* Trash extraneous parameters */
  6649.  
  6650.  if (bp->syntax_error) return NULL;
  6651.  
  6652.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for EXTRACT command");
  6653.  
  6654.  if (cmdp) {
  6655.    cmdp->mode = PER_ARTICLE_MODE;
  6656.    cmdp->proc = NNMbxext;
  6657.    cmdp->cmd.xcmd.extracting = NO_EXTRACTING_MODE;
  6658.  }
  6659.  
  6660.  return cmdp;
  6661. }
  6662.  
  6663. /****** Parse batch EXTRACT      command. ****************************/
  6664.  
  6665. struct newscmd *
  6666. NNMbpext(np,bp)
  6667. Rstruc nncb         *np;
  6668. Rstruc batch        *bp;
  6669. {
  6670.  
  6671.  switch (bp->mode) {
  6672.    case PER_NEWSGROUP_MODE: return parse_newsgroup_extract (np,bp);
  6673.    case PER_ARTICLE_MODE:   return parse_article_extract   (np,bp);
  6674.    default:
  6675.         NNMbsynt(np,bp,NULL,0,
  6676.         "EXTRACT belongs in per-newsgroup mode or per-article mode");
  6677.    return NULL;
  6678.  }
  6679.  
  6680. }
  6681.  
  6682. ./   ADD NAME=NNMBPFOR,SSI=01010010
  6683.  
  6684.  /********************************************************************/
  6685.  /*                                                                  */
  6686.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  6687.  /*                                                                  */
  6688.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  6689.  /* including the implied warranties of merchantability and fitness, */
  6690.  /* are expressly denied.                                            */
  6691.  /*                                                                  */
  6692.  /* Provided this copyright notice is included, this software may    */
  6693.  /* be freely distributed and not offered for sale.                  */
  6694.  /*                                                                  */
  6695.  /* Changes or modifications may be made and used only by the maker  */
  6696.  /* of same, and not further distributed.  Such modifications should */
  6697.  /* be mailed to the author for consideration for addition to the    */
  6698.  /* software and incorporation in subsequent releases.               */
  6699.  /*                                                                  */
  6700.  /********************************************************************/
  6701.  
  6702. /*=====================================================================
  6703.  *
  6704.  * Command: FOR
  6705.  *
  6706.  * Syntax:  (1) in top-level mode...
  6707.  *
  6708.  *          FOR criterion {WHEN filter} DO;
  6709.  *          command(s);
  6710.  *          END;
  6711.  *
  6712.  *          where
  6713.  *
  6714.  *          criterion is one of: ALL
  6715.  *                               REGISTERED
  6716.  *                               UNREGISTERED
  6717.  *           * not implemented:  "groupmask"  (e.g. "comp*")
  6718.  *           * not implemented:  {NEWS}GROUP{S} "groupnames"
  6719.  *
  6720.  *          filter is any flag expression
  6721.  *
  6722.  *          commands are any commands for the appropriate mode
  6723.  *
  6724.  * Examples:
  6725.  *
  6726.  *   FOR ALL                  DO ... { per-newsgroup commands }
  6727.  *   FOR REGISTERED           DO ...
  6728.  *   FOR ... WHEN (READ = nn) DO ...
  6729.  *   FOR ... WHEN (UNREAD > nn) DO ...
  6730.  *   FOR ... WHEN (COUNT < nn) DO ...
  6731.  *   the following are not implemented:
  6732.  *   FOR "comp.*"             DO ...
  6733.  *   FOR GROUPS "a.b.c d.e.f" DO ...
  6734.  *   FOR NEWSGROUP "a.b.c" DO ...
  6735.  *
  6736.  * Syntax:  (2) in per-newsgroup mode...
  6737.  *
  6738.  *          FOR criterion {WHEN filter} DO;
  6739.  *          command(s);
  6740.  *          END;
  6741.  *
  6742.  *          where
  6743.  *
  6744.  *          criterion is one of: ALL
  6745.  *                               READ
  6746.  *                               UNREAD
  6747.  *                               i TO j  (i = number or FIRST,
  6748.  *                                       (j = number or LAST)
  6749.  *
  6750.  *          filter is any flag expression
  6751.  *
  6752.  *          commands are any commands for the appropriate mode
  6753.  *
  6754.  * Examples:
  6755.  *
  6756.  * FOR ALL WHEN "foo" IN SUBJECT DO ...
  6757.  * FOR UNREAD DO ...
  6758.  * FOR FIRST TO 10 DO ...
  6759.  *
  6760.  * Mode:    (1) top-level     (picking newsgroups)
  6761.  *          (2) per-newsgroup (picking articles)
  6762.  *
  6763.  * For (1), the commands between DO and END are in per-newsgroup mode.
  6764.  * For (2), the commands between DO and END are in per-article mode.
  6765.  *
  6766.  * Function: Defines operations to be performed on each newsgroup
  6767.  *           in a list of newsgroups (1), or on each article in a
  6768.  *           list of articles (2).
  6769.  *
  6770.  *
  6771.  *====================================================================*/
  6772.  
  6773. #pragma  csect(code,  "NN@BPFOR")
  6774. #pragma  csect(static,"NN$BPFOR")
  6775. #include "nn.h"
  6776. #include "nnbatch.h"
  6777.  
  6778. /****** Get keyword. *************************************************/
  6779.  
  6780. static Bool
  6781. get_keyword(np,bp,key)
  6782. Rstruc nncb                 *np;
  6783. Rstruc batch                *bp;
  6784. char                        *key;
  6785. {
  6786.  struct token               *tp;
  6787.  
  6788.  if ((tp = PEEK()) && tp->type == WORD_TOKEN && EQUAL(tp->string,key)) {
  6789.    EAT();
  6790.    return TRUE;
  6791.  }
  6792.  
  6793.  else return FALSE;
  6794.  
  6795. }
  6796.  
  6797. /****** Parse initial-mode FOR for newsgroups. ***********************/
  6798.  
  6799. static struct newscmd *
  6800. parse_for_newsgroups(np,bp)
  6801. Rstruc nncb                 *np;
  6802. Rstruc batch                *bp;
  6803. {
  6804.  struct token               *tp;
  6805.  struct newscmd             *cmdp       = NULL;
  6806.  struct ptree               *filter     = NULL;
  6807.  struct cmdtree             *treep      = NULL;
  6808.  struct ptree               *groups     = NULL;
  6809.  enum which_newsgroups       which      = NO_NEWSGROUPS;
  6810.  
  6811.  /* Look for criterion, one of:
  6812.   *                              ALL
  6813.   *                              REGISTERED
  6814.   *                              UNREGISTERED
  6815.   *  (not implemented)           GROUPMASK group-mask-expression
  6816.   *                              {NEWS}GROUP{S} group-name-expression
  6817.   */
  6818.  
  6819.  if ((tp = PEEK())) {
  6820.    switch (tp->type) {
  6821.      case WORD_TOKEN:
  6822.                          if      (EQUAL(tp->string,"ALL")) {
  6823.                            EAT();
  6824.                            which = ALL_NEWSGROUPS;
  6825.                          }
  6826.                          else if (EQUAL(tp->string,"REGISTERED")) {
  6827.                            EAT();
  6828.                            which = REGISTERED_NEWSGROUPS;
  6829.                          }
  6830.                          else if (EQUAL(tp->string,"UNREGISTERED")) {
  6831.                            EAT();
  6832.                            which = UNREGISTERED_NEWSGROUPS;
  6833.                          }
  6834.                          else if (EQUAL(tp->string,"GROUP")
  6835.                                || EQUAL(tp->string,"GROUPS")
  6836.                                || EQUAL(tp->string,"NEWSGROUP")
  6837.                                || EQUAL(tp->string,"NEWSGROUPS")) {
  6838.                            EAT();
  6839.                            which = NAMED_NEWSGROUPS;
  6840.                          }
  6841.                          else if (EQUAL(tp->string,"GROUPMASK")
  6842.                                || EQUAL(tp->string,"NEWSGROUPMASK")) {
  6843.                            EAT();
  6844.                            which = MASKED_NEWSGROUPS;
  6845.                          }
  6846.                          break;
  6847.      case STRING_TOKEN:  if (strchr(tp->string,'*'))
  6848.                               which = MASKED_NEWSGROUPS;
  6849.                          else which = NAMED_NEWSGROUPS;
  6850.                          break;
  6851.      default:
  6852.                          break;
  6853.    }
  6854.  }
  6855.  
  6856.  switch (which) {
  6857.    case NO_NEWSGROUPS:
  6858.                            NNMbsynt(np,bp,NULL,0,
  6859.   "Missing FOR criterion - ALL, REGISTERED, UNREGISTERED, NEWSGROUPS");
  6860.                            break;
  6861.    case NAMED_NEWSGROUPS:
  6862.                            groups = NNMbgexp(np,bp,STRING_SYMTYPE);
  6863.                            if (!groups) NNMbsynt(np,bp,NULL,0,
  6864.                                       "No valid group list specified");
  6865.                            break;
  6866.    case MASKED_NEWSGROUPS:
  6867.                            groups = NNMbgexp(np,bp,STRING_SYMTYPE);
  6868.                            if (!groups) NNMbsynt(np,bp,NULL,0,
  6869.                                       "No valid group mask specified");
  6870.                            break;
  6871.    default: break;
  6872.  }
  6873.  
  6874.  /* Look for WHEN.  If found, then look for filter, a flag expression.
  6875.   */
  6876.  
  6877.  if (get_keyword(np,bp,"WHEN")) {
  6878.    filter = NNMbgexp(np,bp,FLAG_SYMTYPE);
  6879.    if (!filter) {
  6880.      NNMbsynt(np,bp,NULL,0,"No valid filter expression specified");
  6881.    }
  6882.  }
  6883.  
  6884.  /* Get DO-END command group.  */
  6885.  
  6886.  treep = NNMbgdo(np,bp,PER_NEWSGROUP_MODE);
  6887.  
  6888.  if (bp->syntax_error) return NULL;
  6889.  
  6890.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for FOR command");
  6891.  
  6892.  if (cmdp) {
  6893.    cmdp->mode = INITIAL_MODE;
  6894.    cmdp->proc = NNMbxfng;
  6895.    cmdp->cmd.icmd.fors.filter          = filter;
  6896.    cmdp->cmd.icmd.fors.treep           = treep;
  6897.    cmdp->cmd.icmd.fors.crit.which      = which;
  6898.    cmdp->cmd.icmd.fors.crit.groups     = groups;
  6899.  }
  6900.  
  6901.  return cmdp;
  6902.  
  6903. }
  6904.  
  6905. /****** Parse per-newsgroup-mode FOR for articles. *******************/
  6906.  
  6907. static struct newscmd *
  6908. parse_for_articles(np,bp)
  6909. Rstruc nncb                 *np;
  6910. Rstruc batch                *bp;
  6911. {
  6912.  struct token               *tp;
  6913.  struct newscmd             *cmdp        = NULL;
  6914.  struct ptree               *filter      = NULL;
  6915.  struct cmdtree             *treep       = NULL;
  6916.  struct ptree               *first       = NULL;
  6917.  struct ptree               *last        = NULL;
  6918.  enum which_articles         which       = NO_ARTICLES;
  6919.  
  6920.  /* Look for criterion, one of:
  6921.   *                              ALL
  6922.   *                              READ
  6923.   *                              UNREAD
  6924.   *                              i/FIRST to j/LAST
  6925.   *
  6926.   * Note: FIRST and LAST will be variables at run time, making it
  6927.   *       easier to handle them.  That way you can say things like
  6928.   *       FIRST + 1 TO LAST - 3.
  6929.   */
  6930.  
  6931.  if ((tp = PEEK())) {
  6932.    switch (tp->type) {
  6933.      case WORD_TOKEN:
  6934.                          if      (EQUAL(tp->string,"ALL")) {
  6935.                            EAT();
  6936.                            which = ALL_ARTICLES;
  6937.                          }
  6938.                          else if (EQUAL(tp->string,"READ")) {
  6939.                            EAT();
  6940.                            which = READ_ARTICLES;
  6941.                          }
  6942.                          else if (EQUAL(tp->string,"UNREAD")) {
  6943.                            EAT();
  6944.                            which = UNREAD_ARTICLES;
  6945.                          }
  6946.                          else which = RANGED_ARTICLES;
  6947.                          break;
  6948.      default:            which = RANGED_ARTICLES;
  6949.                          break;
  6950.    }
  6951.  }
  6952.  
  6953.  switch (which) {
  6954.    case NO_ARTICLES:
  6955.                          NNMbsynt(np,bp,NULL,0,
  6956.   "Missing FOR criterion - ALL, READ, UNREAD, or n/FIRST to n/LAST");
  6957.                          break;
  6958.    case RANGED_ARTICLES:
  6959.                          first = NNMbgexp(np,bp,NUMBER_SYMTYPE);
  6960.                          if (!first) NNMbsynt(np,bp,NULL,0,
  6961.                                      "No valid range start given");
  6962.                          if (get_keyword(np,bp,"TO")) {
  6963.                            last = NNMbgexp(np,bp,NUMBER_SYMTYPE);
  6964.                            if (!last) NNMbsynt(np,bp,NULL,0,
  6965.                                       "No valid range end given");
  6966.                          }
  6967.                          else last = NULL;
  6968.                          break;
  6969.    default: break;
  6970.  }
  6971.  
  6972.  /* Look for WHEN.  If found, then look for filter, a flag expression.*/
  6973.  
  6974.  if (get_keyword(np,bp,"WHEN")) {
  6975.    filter = NNMbgexp(np,bp,FLAG_SYMTYPE);
  6976.    if (!filter) {
  6977.      NNMbsynt(np,bp,NULL,0,"No valid filter expression specified");
  6978.    }
  6979.  }
  6980.  
  6981.  /* Get DO-END command group.  */
  6982.  
  6983.  treep = NNMbgdo(np,bp,PER_ARTICLE_MODE);
  6984.  
  6985.  if (bp->syntax_error) return NULL;
  6986.  
  6987.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for FOR command");
  6988.  
  6989.  if (cmdp) {
  6990.    cmdp->mode = PER_NEWSGROUP_MODE;
  6991.    cmdp->proc = NNMbxfar;
  6992.    cmdp->cmd.ncmd.fors.filter     = filter;
  6993.    cmdp->cmd.ncmd.fors.treep      = treep;
  6994.    cmdp->cmd.ncmd.fors.crit.which = which;
  6995.    cmdp->cmd.ncmd.fors.crit.first = first;
  6996.    cmdp->cmd.ncmd.fors.crit.last  = last;
  6997.  }
  6998.  
  6999.  return cmdp;
  7000.  
  7001. }
  7002.  
  7003. /****** Parse batch FOR          command. ****************************/
  7004.  
  7005. struct newscmd *
  7006. NNMbpfor(np,bp)
  7007. Rstruc nncb         *np;
  7008. Rstruc batch        *bp;
  7009. {
  7010.  
  7011.  switch (bp->mode) {
  7012.    case INITIAL_MODE:       return parse_for_newsgroups(np,bp);
  7013.    case PER_NEWSGROUP_MODE: return parse_for_articles  (np,bp);
  7014.    default: NNMbsynt(np,bp,NULL,0,
  7015.                  "FOR belongs in initial mode or per-newsgroup mode");
  7016.             return NULL;
  7017.  }
  7018.  
  7019. }
  7020.  
  7021. ./   ADD NAME=NNMBPHEL,SSI=01000013
  7022.  
  7023.  /********************************************************************/
  7024.  /*                                                                  */
  7025.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  7026.  /*                                                                  */
  7027.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  7028.  /* including the implied warranties of merchantability and fitness, */
  7029.  /* are expressly denied.                                            */
  7030.  /*                                                                  */
  7031.  /* Provided this copyright notice is included, this software may    */
  7032.  /* be freely distributed and not offered for sale.                  */
  7033.  /*                                                                  */
  7034.  /* Changes or modifications may be made and used only by the maker  */
  7035.  /* of same, and not further distributed.  Such modifications should */
  7036.  /* be mailed to the author for consideration for addition to the    */
  7037.  /* software and incorporation in subsequent releases.               */
  7038.  /*                                                                  */
  7039.  /********************************************************************/
  7040.  
  7041. /*=====================================================================
  7042.  *
  7043.  * Command: HELP
  7044.  *
  7045.  * Syntax:  HELP {word}*
  7046.  *
  7047.  * Mode:    any
  7048.  *
  7049.  * Function: Writes help information to the output file.
  7050.  *
  7051.  * Note: Words may be specified, but are currently ignored.  All
  7052.  *       arguments are flushed until a new line or ';' is seen.
  7053.  *
  7054.  * Examples:  HELP
  7055.  *            HELP FOR
  7056.  *            HELP "anything" (at all), it doesn't matter!
  7057.  *
  7058.  *====================================================================*/
  7059.  
  7060. #pragma  csect(code,  "NN@BPHEL")
  7061. #pragma  csect(static,"NN$BPHEL")
  7062. #include "nn.h"
  7063. #include "nnbatch.h"
  7064.  
  7065. /****** Execute batch HELP       command. ****************************/
  7066.  
  7067. static void
  7068. NNMbxhel(np,bp,cmdp)
  7069. Rstruc nncb         *np;
  7070. Rstruc batch        *bp;
  7071. Rstruc newscmd      *cmdp;
  7072. {
  7073.  FILE               *helpfp;
  7074.  char                helpline[257];
  7075.  
  7076.  if (!(helpfp = fopen("DD:NNBATHLP","r"))) {
  7077.    perror("ddname NNBATHLP");
  7078.    fprintf(np->batch_outfile,
  7079.      "\n\n*** Help not available - cannot open batch help file. ***\n");
  7080.    return;
  7081.  }
  7082.  for (;;) {
  7083.    fgets(helpline, sizeof(helpline), helpfp);
  7084.    if (feof(helpfp))  break;
  7085.    if (ferror(helpfp)) {
  7086.      fprintf(np->batch_outfile,
  7087.            "\n\n*** Help terminated - error reading help file. ***\n");
  7088.      break;
  7089.    }
  7090.    fprintf(np->batch_outfile,"%s",helpline);
  7091.  }
  7092.  fprintf(np->batch_outfile,"\n");
  7093.  fclose(helpfp);
  7094.  
  7095.  return; 
  7096. }
  7097.  
  7098. /****** Parse batch HELP         command. ****************************/
  7099.  
  7100. struct newscmd *
  7101. NNMbphel(np,bp)
  7102. Rstruc nncb         *np;
  7103. Rstruc batch        *bp;
  7104. {
  7105.  struct newscmd     *cmdp;
  7106.  
  7107.  bp->stop_at_newline = TRUE;
  7108.  
  7109.  while (NNMbgtok(np,bp,TOKEN_READ)) { /* Get token */
  7110.    switch (bp->curtok.type) {
  7111.      case EOF_TOKEN:
  7112.      case EOL_TOKEN:
  7113.      case SEMI_TOKEN: break;
  7114.      default:         NNMbsynt(np,bp,bp->curtok.string,0,
  7115.                                "Extraneous parameter for HELP");
  7116.                       continue;
  7117.    }
  7118.    break;
  7119.  }
  7120.  
  7121.  if (bp->syntax_error) return NULL;
  7122.  
  7123.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for HELP command");
  7124.  
  7125.  if (cmdp) {
  7126.    cmdp->mode = ANY_MODE;
  7127.    cmdp->proc = NNMbxhel;
  7128.  }
  7129.  
  7130.  return cmdp;
  7131.  
  7132. }
  7133.  
  7134. ./   ADD NAME=NNMBPIF,SSI=01000031
  7135.  
  7136.  /********************************************************************/
  7137.  /*                                                                  */
  7138.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  7139.  /*                                                                  */
  7140.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  7141.  /* including the implied warranties of merchantability and fitness, */
  7142.  /* are expressly denied.                                            */
  7143.  /*                                                                  */
  7144.  /* Provided this copyright notice is included, this software may    */
  7145.  /* be freely distributed and not offered for sale.                  */
  7146.  /*                                                                  */
  7147.  /* Changes or modifications may be made and used only by the maker  */
  7148.  /* of same, and not further distributed.  Such modifications should */
  7149.  /* be mailed to the author for consideration for addition to the    */
  7150.  /* software and incorporation in subsequent releases.               */
  7151.  /*                                                                  */
  7152.  /********************************************************************/
  7153.  
  7154. /*=====================================================================
  7155.  *
  7156.  * Command: IF
  7157.  *
  7158.  * Syntax:  IF condition THEN DO;
  7159.  *          command(s);
  7160.  *          END;
  7161.  *          ELSE DO;
  7162.  *          command(s);
  7163.  *          END;
  7164.  *
  7165.  *          where
  7166.  *
  7167.  *          condition is any flag expression
  7168.  *
  7169.  *          commands are any commands for the appropriate mode
  7170.  *
  7171.  * Examples:
  7172.  *
  7173.  *   IF AUTOREGISTER THEN DO ...
  7174.  *   IF SERVER != "" THEN DO ...
  7175.  *   IF (A = 1 | B = 2)  THEN DO ...
  7176.  *
  7177.  * Mode:    any (but see note)
  7178.  *
  7179.  * The commands between DO and END, for the THEN and ELSE groups,
  7180.  * must be in the appropriate mode.
  7181.  *
  7182.  * Function: If condition is true, executes commands in the first
  7183.  *           command group; otherwise executes commands in the second
  7184.  *           command group.
  7185.  *
  7186.  *====================================================================*/
  7187.  
  7188. #pragma  csect(code,  "NN@BPIF ")
  7189. #pragma  csect(static,"NN$BPIF ")
  7190. #include "nn.h"
  7191. #include "nnbatch.h"
  7192.  
  7193. /****** Execute commands. ********************************************/
  7194.  
  7195. static void
  7196. execute_commands(np,bp,treep)
  7197. Rstruc nncb                 *np;
  7198. Rstruc batch                *bp;
  7199. struct cmdtree              *treep;
  7200. {
  7201.  
  7202.  for (; treep; treep = treep->next) {
  7203.    bp->runtime_error = FALSE;
  7204.    (treep->cmd->proc) (np,bp,treep->cmd);
  7205.    SETB("ERROR",bp->runtime_error);
  7206.  }
  7207.  
  7208.  return; 
  7209. }
  7210.  
  7211. /****** Execute batch IF command. ************************************/
  7212.  
  7213. static void
  7214. NNMbxif(np,bp,cmdp)
  7215. Rstruc nncb                 *np;
  7216. Rstruc batch                *bp;
  7217. Rstruc newscmd              *cmdp;
  7218. {
  7219.  struct ptree               *condition;
  7220.  struct cmdtree             *thencmds;
  7221.  struct cmdtree             *elsecmds;
  7222.  Fool                        condval;
  7223.  
  7224.  condition = cmdp->cmd.fcmd.condition;
  7225.  thencmds  = cmdp->cmd.fcmd.thencmds;
  7226.  elsecmds  = cmdp->cmd.fcmd.elsecmds;
  7227.  
  7228.  condval = (Fool) NNMbbexp(np,bp,condition,FLAG_SYMTYPE);
  7229.  if (bp->runtime_error) return;
  7230.  
  7231.  if (condval) execute_commands(np,bp,thencmds);
  7232.  else         execute_commands(np,bp,elsecmds);
  7233.  
  7234.  return; 
  7235. }
  7236.  
  7237. /****** Get keyword. *************************************************/
  7238.  
  7239. static Bool
  7240. get_keyword(np,bp,key)
  7241. Rstruc nncb                 *np;
  7242. Rstruc batch                *bp;
  7243. char                        *key;
  7244. {
  7245.  struct token               *tp;
  7246.  
  7247.  if ((tp = PEEK())
  7248.   && tp->type == WORD_TOKEN
  7249.   && EQUAL(tp->string,key)) {
  7250.    EAT();
  7251.    return TRUE;
  7252.  }
  7253.  
  7254.  else return FALSE;
  7255.  
  7256. }
  7257.  
  7258. /****** Parse batch IF           command. ****************************/
  7259.  
  7260. struct newscmd *
  7261. NNMbpif(np,bp)
  7262. Rstruc nncb         *np;
  7263. Rstruc batch        *bp;
  7264. {
  7265.  struct newscmd             *cmdp       = NULL;
  7266.  struct ptree               *condition  = NULL;
  7267.  struct cmdtree             *thencmds   = NULL;
  7268.  
  7269.  /* Look for condition */
  7270.  
  7271.  condition = NNMbgexp(np,bp,FLAG_SYMTYPE);
  7272.  
  7273.  if (condition == NULL) {
  7274.    NNMbsynt(np,bp,NULL,0,"Missing IF condition");
  7275.    return NULL;
  7276.  }
  7277.  
  7278.  /* Look for THEN (required).  */
  7279.  
  7280.  if (!(get_keyword(np,bp,"THEN"))) {
  7281.    NNMbsynt(np,bp,NULL,0,"Missing THEN keyword");
  7282.    return NULL;
  7283.  }
  7284.  
  7285.  /* Get DO-END command group.
  7286.   */
  7287.  
  7288.  thencmds = NNMbgdo(np,bp,bp->mode);
  7289.  
  7290.  if (bp->syntax_error) return NULL;
  7291.  
  7292.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for IF command");
  7293.  
  7294.  if (cmdp) {
  7295.    cmdp->mode = bp->mode;
  7296.    cmdp->proc = NNMbxif;
  7297.    cmdp->cmd.fcmd.condition  = condition;
  7298.    cmdp->cmd.fcmd.thencmds   = thencmds;
  7299.    cmdp->cmd.fcmd.elsecmds   = NULL;
  7300.  }
  7301.  
  7302.  /* Make sure any following ELSE is properly handled. */
  7303.  
  7304.  bp->ifcmd = cmdp;
  7305.  
  7306.  return cmdp;
  7307.  
  7308. }
  7309.  
  7310. ./   ADD NAME=NNMBPLIS,SSI=01020057
  7311.  
  7312.  /********************************************************************/
  7313.  /*                                                                  */
  7314.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  7315.  /*                                                                  */
  7316.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  7317.  /* including the implied warranties of merchantability and fitness, */
  7318.  /* are expressly denied.                                            */
  7319.  /*                                                                  */
  7320.  /* Provided this copyright notice is included, this software may    */
  7321.  /* be freely distributed and not offered for sale.                  */
  7322.  /*                                                                  */
  7323.  /* Changes or modifications may be made and used only by the maker  */
  7324.  /* of same, and not further distributed.  Such modifications should */
  7325.  /* be mailed to the author for consideration for addition to the    */
  7326.  /* software and incorporation in subsequent releases.               */
  7327.  /*                                                                  */
  7328.  /********************************************************************/
  7329.  
  7330. /*=====================================================================
  7331.  *
  7332.  * Command: LIST
  7333.  *
  7334.  * Syntax:  LIST
  7335.  *
  7336.  * Mode:    per_article
  7337.  *
  7338.  * Function: Lists the contents of the current news article.
  7339.  *
  7340.  * Note: Arguments are not permitted.  If they are given, the
  7341.  *       function will not be performed.
  7342.  *
  7343.  * Examples:  LIST
  7344.  *
  7345.  *====================================================================*/
  7346.  
  7347. #pragma  csect(code,  "NN@BPLIS")
  7348. #pragma  csect(static,"NN$BPLIS")
  7349. #include "nn.h"
  7350. #include "nnbatch.h"
  7351.  
  7352. /********** Execute batch LIST command. ******************************/
  7353.  
  7354. static void
  7355. NNMbxlis(np,bp,cmdp)
  7356. Rstruc nncb         *np;
  7357. Rstruc batch        *bp;
  7358. Rstruc newscmd      *cmdp;
  7359. {
  7360.  Rstruc newsarticle *ap = VARK2PARTICLE(*bp->vp);
  7361.  
  7362.  NNMpick(np,ap);                  /* Pick article */
  7363.  
  7364.  NNMbtext(np,&ap->thdr,NULL);     /* Print text */
  7365.  
  7366.  return; 
  7367.  
  7368. }
  7369.  
  7370. /****** Parse batch LIST command. ************************************/
  7371.  
  7372. struct newscmd *
  7373. NNMbplis(np,bp)
  7374. Rstruc nncb         *np;
  7375. Rstruc batch        *bp;
  7376. {
  7377.  struct newscmd     *cmdp;
  7378.  
  7379.  bp->stop_at_newline = TRUE;
  7380.  
  7381.  NNMbtras(np,bp,"LIST");   /* Trash extraneous parameters */
  7382.  
  7383.  if (bp->syntax_error) return NULL;
  7384.  
  7385.  if (bp->mode != PER_ARTICLE_MODE) {
  7386.    NNMbsynt(np,bp,NULL,0,"LIST is invalid outside of per-article mode");
  7387.    return NULL;
  7388.  }
  7389.  
  7390.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for LIST command");
  7391.  
  7392.  if (cmdp) {
  7393.    cmdp->mode = PER_ARTICLE_MODE;
  7394.    cmdp->proc = NNMbxlis;
  7395.  }
  7396.  
  7397.  return cmdp;
  7398.  
  7399. }
  7400.  
  7401. ./   ADD NAME=NNMBPMAR,SSI=01030025
  7402.  
  7403.  /********************************************************************/
  7404.  /*                                                                  */
  7405.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  7406.  /*                                                                  */
  7407.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  7408.  /* including the implied warranties of merchantability and fitness, */
  7409.  /* are expressly denied.                                            */
  7410.  /*                                                                  */
  7411.  /* Provided this copyright notice is included, this software may    */
  7412.  /* be freely distributed and not offered for sale.                  */
  7413.  /*                                                                  */
  7414.  /* Changes or modifications may be made and used only by the maker  */
  7415.  /* of same, and not further distributed.  Such modifications should */
  7416.  /* be mailed to the author for consideration for addition to the    */
  7417.  /* software and incorporation in subsequent releases.               */
  7418.  /*                                                                  */
  7419.  /********************************************************************/
  7420.  
  7421. /*=====================================================================
  7422.  *
  7423.  * Command: MARK
  7424.  *
  7425.  * Syntax:  MARK { READ / UNREAD }
  7426.  *
  7427.  * Default: MARK READ
  7428.  *
  7429.  * Mode:    per-article
  7430.  *
  7431.  * Function: Marks the article read or unread.
  7432.  *
  7433.  * Examples:  MARK
  7434.  *            MARK READ
  7435.  *            MARK UNREAD
  7436.  *
  7437.  *====================================================================*/
  7438.  
  7439. #pragma  csect(code,  "NN@BPMAR")
  7440. #pragma  csect(static,"NN$BPMAR")
  7441. #include "nn.h"
  7442. #include "nnbatch.h"
  7443.  
  7444. /********** Execute batch MARK command. ******************************/
  7445.  
  7446. static void
  7447. NNMbxmar(np,bp,cmdp)
  7448. Rstruc nncb         *np;
  7449. Rstruc batch        *bp;
  7450. Rstruc newscmd      *cmdp;
  7451. {
  7452.  struct newsgroup   *gp   = bp->gp;
  7453.  VARK               *vp   = bp->vp;
  7454.  char               *what = "not";
  7455.  
  7456.  switch (cmdp->cmd.rcmd.marking) {
  7457.    case MARKING_READ:   NNMmarr(np,gp,vp);
  7458.                         what = "read";
  7459.                         break;
  7460.    case MARKING_UNREAD: NNMmaru(np,gp,vp);
  7461.                         what = "unread";
  7462.                         break;
  7463.  }
  7464.  
  7465.  fprintf(np->batch_outfile, "Article %d of %s marked %s.\n",
  7466.                             VARK2NUMBER(gp,vp), gp->name, what);
  7467.  
  7468.  NNMsave(np,NULL);   /* Checkpoint NEWSRC file */
  7469.  
  7470.  return; 
  7471.  
  7472. }
  7473.  
  7474. /****** Parse batch MARK         command. ****************************/
  7475.  
  7476. struct newscmd *
  7477. NNMbpmar(np,bp)
  7478. Rstruc nncb         *np;
  7479. Rstruc batch        *bp;
  7480. {
  7481.  struct newscmd     *cmdp       = NULL;
  7482.  enum marking_mode   marking    = MARKING_READ;
  7483.  
  7484.  /* Next token, if present, must be READ or UNREAD.  */
  7485.  
  7486.  if (NNMbgtok(np,bp,TOKEN_READ)) {  /* get token */
  7487.    switch (bp->curtok.type) {
  7488.      case EOL_TOKEN:
  7489.      case EOF_TOKEN:
  7490.      case SEMI_TOKEN: marking = MARKING_READ;
  7491.                       break;
  7492.      case WORD_TOKEN: if (EQUAL(bp->curtok.string,"READ")) {
  7493.                         marking = MARKING_READ;
  7494.                       }
  7495.                       else if (EQUAL(bp->curtok.string,"UNREAD")) {
  7496.                         marking = MARKING_UNREAD;
  7497.                       }
  7498.                       else {
  7499.                         NNMbsynt(np,bp,bp->curtok.string,0,
  7500.                                  "MARK operand must be READ or UNREAD");
  7501.                       }
  7502.                       break;
  7503.      default:         NNMbsynt(np,bp,bp->curtok.string,0,
  7504.                                "MARK operand must be READ or UNREAD");
  7505.                       break;
  7506.    }
  7507.  }
  7508.  
  7509.  bp->stop_at_newline = TRUE;
  7510.  
  7511.  NNMbtras(np,bp,"MARK");   /* Trash extraneous parameters */
  7512.  
  7513.  if (bp->syntax_error) return NULL;
  7514.  
  7515.  if (bp->mode != PER_ARTICLE_MODE) {
  7516.    NNMbsynt(np,bp,NULL,0,"MARK is invalid outside of per-article mode");
  7517.    return NULL;
  7518.  }
  7519.  
  7520.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for MARK command");
  7521.  
  7522.  if (cmdp) {
  7523.    cmdp->mode = PER_ARTICLE_MODE;
  7524.    cmdp->proc = NNMbxmar;
  7525.    cmdp->cmd.rcmd.marking = marking;
  7526.  }
  7527.  
  7528.  return cmdp;
  7529. }
  7530.  
  7531. ./   ADD NAME=NNMBPNNT,SSI=01000022
  7532.  
  7533.  /********************************************************************/
  7534.  /*                                                                  */
  7535.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  7536.  /*                                                                  */
  7537.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  7538.  /* including the implied warranties of merchantability and fitness, */
  7539.  /* are expressly denied.                                            */
  7540.  /*                                                                  */
  7541.  /* Provided this copyright notice is included, this software may    */
  7542.  /* be freely distributed and not offered for sale.                  */
  7543.  /*                                                                  */
  7544.  /* Changes or modifications may be made and used only by the maker  */
  7545.  /* of same, and not further distributed.  Such modifications should */
  7546.  /* be mailed to the author for consideration for addition to the    */
  7547.  /* software and incorporation in subsequent releases.               */
  7548.  /*                                                                  */
  7549.  /********************************************************************/
  7550.  
  7551. /*=====================================================================
  7552.  *
  7553.  * Command: NNTP
  7554.  *
  7555.  * Syntax:  NNTP {datum}* ;
  7556.  *
  7557.  * Mode:    any (but see notes)
  7558.  *
  7559.  * Function: Sends an NNTP protocol command to the server as built
  7560.  *           from the specified data items.  Items can be:
  7561.  *
  7562.  *           * text strings
  7563.  *           * integers
  7564.  *           * words representing variables that have values
  7565.  *
  7566.  * Note: When words are used, the values they represent must be
  7567.  *       valid for the mode in which the EXEC is executed.
  7568.  *
  7569.  * Note: The NNTP request must be appropriate for the mode active
  7570.  *       at the time the request is executed.
  7571.  *
  7572.  * Note: Since the command can span input lines and the number of
  7573.  *       arguments is variable, the arguments MUST be terminated
  7574.  *       by a semicolon or end of file.
  7575.  *
  7576.  * Examples:  NNTP "HELP";
  7577.  *            NNTP "ARTICLE " NUMBER;
  7578.  *
  7579.  *====================================================================*/
  7580.  
  7581. #pragma  csect(code,  "NN@BPNNT")
  7582. #pragma  csect(static,"NN$BPNNT")
  7583. #include "nn.h"
  7584. #include "nnbatch.h"
  7585.  
  7586. /****** Execute batch NNTP       command. ****************************/
  7587.  
  7588. static void
  7589. NNMbxnnt(np,bp,cmdp)
  7590. Rstruc nncb         *np;
  7591. Rstruc batch        *bp;
  7592. Rstruc newscmd      *cmdp;
  7593. {
  7594.  char               *string;
  7595.  
  7596.  string = NNMbbexp(np,bp,cmdp->cmd.mcmd.ptreep,STRING_SYMTYPE);
  7597.  if (bp->runtime_error) {
  7598.    fprintf(np->batch_outfile,
  7599.            "NNTP command not sent due to errors building argument\n");
  7600.    return;
  7601.  }
  7602.  
  7603.  if (!NNMbconn(np,bp)) {  /* Insure server name and connect to server */
  7604.    fprintf(np->batch_outfile,"NNTP command not executed:\n%s\n\n",
  7605.                              string);
  7606.    return;
  7607.  }
  7608.  
  7609.  fprintf(np->batch_outfile, "NNTP command:\n%s\n\n", string);
  7610.  
  7611.  if (*string || np->receiving_text) {
  7612.    if (strlen(string) > CLIENT_BUF_MSGSIZE) {
  7613.      ERR1(
  7614.    "Requested NNTP command is longer than NNMVS is prepared to handle."
  7615.          );
  7616.    }
  7617.    else {
  7618.      strcpy(np->nntp_command,string);
  7619.      NNMnntp(np);                       /* execute NNTP commands */
  7620.    }
  7621.  }
  7622.  
  7623.  return; 
  7624.  
  7625. }
  7626.  
  7627. /****** Parse batch NNTP         command. ****************************/
  7628.  
  7629. struct newscmd *
  7630. NNMbpnnt(np,bp)
  7631. Rstruc nncb         *np;
  7632. Rstruc batch        *bp;
  7633. {
  7634.  struct newscmd     *cmdp       = NULL;
  7635.  struct ptree       *treep      = NULL;
  7636.  
  7637.  treep = NNMbgexp(np,bp,STRING_SYMTYPE); /* Get data string struct */
  7638.  
  7639.  if (!treep) {
  7640.    NNMbsynt(np,bp,NULL,0,"Error in arguments to NNTP");
  7641.    return NULL;
  7642.  }
  7643.  
  7644.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for NNTP command");
  7645.  
  7646.  if (cmdp) {
  7647.    cmdp->mode = ANY_MODE;
  7648.    cmdp->proc = NNMbxnnt;
  7649.    cmdp->cmd.mcmd.ptreep = treep;
  7650.  }
  7651.  
  7652.  return cmdp;
  7653. }
  7654.  
  7655. ./   ADD NAME=NNMBPPUT,SSI=01000024
  7656.  
  7657.  /********************************************************************/
  7658.  /*                                                                  */
  7659.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  7660.  /*                                                                  */
  7661.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  7662.  /* including the implied warranties of merchantability and fitness, */
  7663.  /* are expressly denied.                                            */
  7664.  /*                                                                  */
  7665.  /* Provided this copyright notice is included, this software may    */
  7666.  /* be freely distributed and not offered for sale.                  */
  7667.  /*                                                                  */
  7668.  /* Changes or modifications may be made and used only by the maker  */
  7669.  /* of same, and not further distributed.  Such modifications should */
  7670.  /* be mailed to the author for consideration for addition to the    */
  7671.  /* software and incorporation in subsequent releases.               */
  7672.  /*                                                                  */
  7673.  /********************************************************************/
  7674.  
  7675. /*=====================================================================
  7676.  *
  7677.  * Command: PUT
  7678.  *
  7679.  * Syntax:  PUT {datum}* ;
  7680.  *
  7681.  * Mode:    any (but see note)
  7682.  *
  7683.  * Function: Writes zero or more items of data to the output file,
  7684.  *           followed by a newline.  Items can be:
  7685.  *
  7686.  *           * text strings
  7687.  *           * integers
  7688.  *           * words representing variables that have values
  7689.  *
  7690.  * Note: When words are used, the values they represent must be
  7691.  *       valid for the mode in which the PUT is executed.
  7692.  *
  7693.  * Note: Since the command can span input lines and the number of
  7694.  *       arguments is variable, the arguments MUST be terminated
  7695.  *       by a semicolon or end of file.
  7696.  *
  7697.  * Examples:  PUT;
  7698.  *            PUT "Hello, world";
  7699.  *            PUT 666 " is the number of the Beast.";
  7700.  *            PUT "I have " UNREAD " new items from server " server ".";
  7701.  *
  7702.  *====================================================================*/
  7703.  
  7704. #pragma  csect(code,  "NN@BPPUT")
  7705. #pragma  csect(static,"NN$BPPUT")
  7706. #include "nn.h"
  7707. #include "nnbatch.h"
  7708.  
  7709. /****** Print text line. *********************************************/
  7710.  
  7711. static Bool
  7712. print_text_line(fp,string)
  7713. FILE           *fp;
  7714. char           *string;
  7715. {
  7716.  char          *cp;
  7717.  int            l;
  7718.  
  7719.  for (cp = string, l = strlen(string); l > 0; cp += 251, l -= 251) {
  7720.   fwrite(cp,(l>251 ? 251 : l),1,fp);
  7721.   if (ferror(fp))            return FALSE;
  7722.   if (fputc('\n',fp) == EOF) return FALSE;
  7723.  }
  7724.  
  7725.  return TRUE;
  7726. }
  7727.  
  7728. /****** Execute batch PUT        command. ****************************/
  7729.  
  7730. static void
  7731. NNMbxput(np,bp,cmdp)
  7732. Rstruc nncb         *np;
  7733. Rstruc batch        *bp;
  7734. Rstruc newscmd      *cmdp;
  7735. {
  7736.  struct ptree       *treep;
  7737.  char               *string;
  7738.  FILE               *fp;
  7739.  Bool                print_error;
  7740.  
  7741.  treep = cmdp->cmd.mcmd.ptreep;
  7742.  
  7743.  print_error = FALSE;
  7744.  
  7745.  if (!treep) {
  7746.    fp = NNMbsout(np,bp);  /* Set output file */
  7747.    fprintf(fp,"\n");
  7748.    if (ferror(fp)) print_error = TRUE;
  7749.  }
  7750.  else {
  7751.    string = NNMbbexp(np,bp,treep,STRING_SYMTYPE);
  7752.    if (bp->runtime_error) {
  7753.      fprintf(np->batch_outfile,
  7754.              "\n<<Put failed, error building argument>>\n");
  7755.    }
  7756.    else {
  7757.      fp = NNMbsout(np,bp);  /* Set output file */
  7758.      if (!print_text_line(fp,string)) print_error = TRUE;
  7759.    }
  7760.  }
  7761.  
  7762.  if (print_error) {
  7763.    fprintf(stderr,"Error writing to outfile\n");
  7764.    bp->runtime_error = TRUE;
  7765.  }
  7766.  
  7767.  return; 
  7768.  
  7769. }
  7770.  
  7771. /****** Parse batch PUT          command. ****************************/
  7772.  
  7773. struct newscmd *
  7774. NNMbpput(np,bp)
  7775. Rstruc nncb         *np;
  7776. Rstruc batch        *bp;
  7777. {
  7778.  struct newscmd     *cmdp       = NULL;
  7779.  struct ptree       *treep      = NULL;
  7780.  
  7781.  /*
  7782.   * Special case for PUT without arguments
  7783.   *
  7784.   */
  7785.  
  7786.  if (NNMbgtok(np,bp,TOKEN_PEEK)) {  /* Peek next token */
  7787.    switch (bp->nextok.type) {
  7788.      case EOF_TOKEN:
  7789.      case EOL_TOKEN:
  7790.      case SEMI_TOKEN:  treep = NULL;
  7791.                        break;
  7792.      default:
  7793.                        treep = NNMbgexp(np,bp,STRING_SYMTYPE);
  7794.                        if (!treep) {
  7795.                          NNMbsynt(np,bp,NULL,0,
  7796.                                   "Error in arguments to PUT");
  7797.                          return NULL;
  7798.                        }
  7799.                        break;
  7800.    }
  7801.  }
  7802.  
  7803.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for PUT command");
  7804.  
  7805.  if (cmdp) {
  7806.    cmdp->mode = ANY_MODE;
  7807.    cmdp->proc = NNMbxput;
  7808.    cmdp->cmd.mcmd.ptreep = treep;
  7809.  }
  7810.  
  7811.  return cmdp;
  7812. }
  7813.  
  7814. ./   ADD NAME=NNMBPQUE,SSI=01010013
  7815.  
  7816.  /********************************************************************/
  7817.  /*                                                                  */
  7818.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  7819.  /*                                                                  */
  7820.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  7821.  /* including the implied warranties of merchantability and fitness, */
  7822.  /* are expressly denied.                                            */
  7823.  /*                                                                  */
  7824.  /* Provided this copyright notice is included, this software may    */
  7825.  /* be freely distributed and not offered for sale.                  */
  7826.  /*                                                                  */
  7827.  /* Changes or modifications may be made and used only by the maker  */
  7828.  /* of same, and not further distributed.  Such modifications should */
  7829.  /* be mailed to the author for consideration for addition to the    */
  7830.  /* software and incorporation in subsequent releases.               */
  7831.  /*                                                                  */
  7832.  /********************************************************************/
  7833.  
  7834. /*=====================================================================
  7835.  *
  7836.  * Command: QUERY
  7837.  *
  7838.  * Syntax:  QUERY
  7839.  *
  7840.  * Mode:    per_newsgroup or per_article
  7841.  *
  7842.  * Function: Dumps the status of the current newsgroup or article.
  7843.  *
  7844.  * Examples:  QUERY
  7845.  *
  7846.  *====================================================================*/
  7847.  
  7848. #pragma  csect(code,  "NN@BPQUE")
  7849. #pragma  csect(static,"NN$BPQUE")
  7850. #include "nn.h"
  7851. #include "nnbatch.h"
  7852.  
  7853. /****** Execute batch QUERY      command. ****************************/
  7854.  
  7855. static void
  7856. NNMbxque(np,bp,cmdp)
  7857. Rstruc nncb         *np;
  7858. Rstruc batch        *bp;
  7859. Rstruc newscmd      *cmdp;
  7860. {
  7861.  
  7862.  switch (cmdp->mode) {
  7863.    case PER_NEWSGROUP_MODE:  NNMqng(np,bp->gp);                 break;
  7864.    case PER_ARTICLE_MODE:    NNMqar(np,VARK2PARTICLE(*bp->vp)); break;
  7865.  }
  7866.  
  7867.  return; 
  7868. }
  7869.  
  7870. /****** Parse batch QUERY        command. ****************************/
  7871.  
  7872. struct newscmd *
  7873. NNMbpque(np,bp)
  7874. Rstruc nncb         *np;
  7875. Rstruc batch        *bp;
  7876. {
  7877.  struct newscmd     *cmdp;
  7878.  
  7879.  bp->stop_at_newline = TRUE;
  7880.  
  7881.  NNMbtras(np,bp,"QUERY");        /* Trash extraneous parameters */
  7882.  
  7883.  if (bp->syntax_error) return NULL;
  7884.  
  7885.  switch (bp->mode) {
  7886.    case PER_NEWSGROUP_MODE:
  7887.    case PER_ARTICLE_MODE:
  7888.         break;
  7889.    default:
  7890.         NNMbsynt(np,bp,NULL,0,
  7891.             "QUERY is valid only in per-newsgroup or per-article mode");
  7892.    return NULL;
  7893.  }
  7894.  
  7895.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for QUERY command");
  7896.  
  7897.  if (cmdp) {
  7898.    cmdp->mode = bp->mode;
  7899.    cmdp->proc = NNMbxque;
  7900.  }
  7901.  
  7902.  return cmdp;
  7903.  
  7904. }
  7905.  
  7906. ./   ADD NAME=NNMBPQUI,SSI=01000018
  7907.  
  7908.  /********************************************************************/
  7909.  /*                                                                  */
  7910.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  7911.  /*                                                                  */
  7912.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  7913.  /* including the implied warranties of merchantability and fitness, */
  7914.  /* are expressly denied.                                            */
  7915.  /*                                                                  */
  7916.  /* Provided this copyright notice is included, this software may    */
  7917.  /* be freely distributed and not offered for sale.                  */
  7918.  /*                                                                  */
  7919.  /* Changes or modifications may be made and used only by the maker  */
  7920.  /* of same, and not further distributed.  Such modifications should */
  7921.  /* be mailed to the author for consideration for addition to the    */
  7922.  /* software and incorporation in subsequent releases.               */
  7923.  /*                                                                  */
  7924.  /********************************************************************/
  7925.  
  7926. /*=====================================================================
  7927.  *
  7928.  * Command: QUIT
  7929.  *
  7930.  * Syntax:  QUIT
  7931.  *
  7932.  * Mode:    any
  7933.  *
  7934.  * Function: Terminates processing when it is seen.
  7935.  *
  7936.  * Note: Arguments are not permitted.  If they are given, the QUIT
  7937.  *       function will not be performed.
  7938.  *
  7939.  * Examples:  QUIT
  7940.  *
  7941.  *====================================================================*/
  7942.  
  7943. #pragma  csect(code,  "NN@BPQUI")
  7944. #pragma  csect(static,"NN$BPQUI")
  7945. #include "nn.h"
  7946. #include "nnbatch.h"
  7947.  
  7948. /****** Execute batch QUIT       command. ****************************/
  7949.  
  7950. static void
  7951. NNMbxqui(np,bp,cmdp)
  7952. Rstruc nncb         *np;
  7953. Rstruc batch        *bp;
  7954. Rstruc newscmd      *cmdp;
  7955. {
  7956.  
  7957.  bp->quit = TRUE;
  7958.  
  7959.  fprintf(np->batch_outfile,"\nQUIT signalled.  Processing ended.\n");
  7960.  
  7961.  return; 
  7962.  
  7963. }
  7964.  
  7965. /****** Parse batch QUIT         command. ****************************/
  7966.  
  7967. struct newscmd *
  7968. NNMbpqui(np,bp)
  7969. Rstruc nncb         *np;
  7970. Rstruc batch        *bp;
  7971. {
  7972.  struct newscmd     *cmdp;
  7973.  
  7974.  bp->stop_at_newline = TRUE;
  7975.  
  7976.  NNMbtras(np,bp,"QUIT");   /* Trash extraneous parameters */
  7977.  
  7978.  if (bp->syntax_error) return NULL;
  7979.  
  7980.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for QUIT command");
  7981.  
  7982.  if (cmdp) {
  7983.    cmdp->mode = ANY_MODE;
  7984.    cmdp->proc = NNMbxqui;
  7985.  }
  7986.  
  7987.  return cmdp;
  7988.  
  7989. }
  7990.  
  7991. ./   ADD NAME=NNMBPREG,SSI=01000034
  7992.  
  7993.  /********************************************************************/
  7994.  /*                                                                  */
  7995.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  7996.  /*                                                                  */
  7997.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  7998.  /* including the implied warranties of merchantability and fitness, */
  7999.  /* are expressly denied.                                            */
  8000.  /*                                                                  */
  8001.  /* Provided this copyright notice is included, this software may    */
  8002.  /* be freely distributed and not offered for sale.                  */
  8003.  /*                                                                  */
  8004.  /* Changes or modifications may be made and used only by the maker  */
  8005.  /* of same, and not further distributed.  Such modifications should */
  8006.  /* be mailed to the author for consideration for addition to the    */
  8007.  /* software and incorporation in subsequent releases.               */
  8008.  /*                                                                  */
  8009.  /********************************************************************/
  8010.  
  8011. /*=====================================================================
  8012.  *
  8013.  * Command: REGISTER
  8014.  *
  8015.  * Syntax:  REGISTER
  8016.  *
  8017.  * Mode:    per_newsgroup
  8018.  *
  8019.  * Function: Registers the current newsgroup.
  8020.  *
  8021.  * Note: Arguments are not permitted.  If they are given, the
  8022.  *       function will not be performed.
  8023.  *
  8024.  * Examples:  REGISTER
  8025.  *
  8026.  *====================================================================*/
  8027.  
  8028. #pragma  csect(code,  "NN@BPREG")
  8029. #pragma  csect(static,"NN$BPREG")
  8030. #include "nn.h"
  8031. #include "nnbatch.h"
  8032.  
  8033. /****** Execute batch REGISTER command. ******************************/
  8034.  
  8035. static void
  8036. NNMbxreg(np,bp,cmdp)
  8037. Rstruc nncb         *np;
  8038. Rstruc batch        *bp;
  8039. Rstruc newscmd      *cmdp;
  8040. {
  8041.  Rstruc newsgroup   *gp = bp->gp;
  8042.  
  8043.  gp->registered = 1;
  8044.  
  8045.  fprintf(np->batch_outfile,"Newsgroup %s registered.\n",gp->name);
  8046.  
  8047.  NNMsave(np,NULL);   /* Checkpoint NEWSRC file */
  8048.  
  8049.  return; 
  8050.  
  8051. }
  8052.  
  8053. /****** Parse batch REGISTER command. ********************************/
  8054.  
  8055. struct newscmd *
  8056. NNMbpreg(np,bp)
  8057. Rstruc nncb         *np;
  8058. Rstruc batch        *bp;
  8059. {
  8060.  struct newscmd     *cmdp;
  8061.  
  8062.  bp->stop_at_newline = TRUE;
  8063.  
  8064.  NNMbtras(np,bp,"REGISTER");   /* Trash extraneous parameters */
  8065.  
  8066.  if (bp->syntax_error) return NULL;
  8067.  
  8068.  if (bp->mode != PER_NEWSGROUP_MODE) {
  8069.    NNMbsynt(np,bp,NULL,0,
  8070.             "REGISTER is invalid outside of per-newsgroup mode");
  8071.    return NULL;
  8072.  }
  8073.  
  8074.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for REGISTER command");
  8075.  
  8076.  if (cmdp) {
  8077.    cmdp->mode = PER_NEWSGROUP_MODE;
  8078.    cmdp->proc = NNMbxreg;
  8079.  }
  8080.  
  8081.  return cmdp;
  8082.  
  8083. }
  8084.  
  8085. ./   ADD NAME=NNMBPSET,SSI=01000038
  8086.  
  8087.  /********************************************************************/
  8088.  /*                                                                  */
  8089.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  8090.  /*                                                                  */
  8091.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  8092.  /* including the implied warranties of merchantability and fitness, */
  8093.  /* are expressly denied.                                            */
  8094.  /*                                                                  */
  8095.  /* Provided this copyright notice is included, this software may    */
  8096.  /* be freely distributed and not offered for sale.                  */
  8097.  /*                                                                  */
  8098.  /* Changes or modifications may be made and used only by the maker  */
  8099.  /* of same, and not further distributed.  Such modifications should */
  8100.  /* be mailed to the author for consideration for addition to the    */
  8101.  /* software and incorporation in subsequent releases.               */
  8102.  /*                                                                  */
  8103.  /********************************************************************/
  8104.  
  8105. /*=====================================================================
  8106.  *
  8107.  * Command: SET
  8108.  *
  8109.  * Syntax:  SET variablename {=} {value-datum}*
  8110.  *
  8111.  * Mode:    any (but see note)
  8112.  *
  8113.  * Function: Assigns a value to the specified variablename so
  8114.  *           that it can be referenced in later PUT statements or
  8115.  *           condition queries.  Value can be made up of:
  8116.  *
  8117.  *           * text strings
  8118.  *           * integers
  8119.  *           * words representing other variables that have values
  8120.  *
  8121.  * Note: When words are used, the values they represent must be
  8122.  *       valid for the mode in which the SET is executed.
  8123.  *
  8124.  * Note: Since the command can span input lines and the number of
  8125.  *       arguments is variable, the arguments MUST be terminated
  8126.  *       by a semicolon or end of file.
  8127.  *
  8128.  * Note: The type of the value is determined by the declared type
  8129.  *       of the variable being set.
  8130.  *
  8131.  * Examples:  SET SERVER "foo.news.com"
  8132.  *            SET COUNT = 1
  8133.  *            SET MESSAGE = "There are " UNREAD "new items."
  8134.  *
  8135.  *====================================================================*/
  8136.  
  8137. #pragma  csect(code,  "NN@BPSET")
  8138. #pragma  csect(static,"NN$BPSET")
  8139. #include "nn.h"
  8140. #include "nnbatch.h"
  8141.  
  8142. /****** Execute batch SET        command. ****************************/
  8143.  
  8144. static void
  8145. NNMbxset(np,bp,cmdp)
  8146. Rstruc nncb         *np;
  8147. Rstruc batch        *bp;
  8148. Rstruc newscmd      *cmdp;
  8149. {
  8150.  char               *string;
  8151.  int                 number;
  8152.  Fool                flag;
  8153.  char               *var;
  8154.  
  8155.  var = cmdp->cmd.scmd.set_symbol;
  8156.  
  8157.  switch (cmdp->cmd.scmd.set_type) {
  8158.    case STRING_SYMTYPE:
  8159.         string = (char *)
  8160.                  NNMbbexp(np,bp,cmdp->cmd.scmd.ptreep,STRING_SYMTYPE);
  8161.         if (!bp->runtime_error) {
  8162.           SETC(var,string);
  8163.         }
  8164.         break;
  8165.    case NUMBER_SYMTYPE:
  8166.         number = (int)
  8167.                  NNMbbexp(np,bp,cmdp->cmd.scmd.ptreep,NUMBER_SYMTYPE);
  8168.         if (!bp->runtime_error) {
  8169.           SETA(var,number);
  8170.         }
  8171.         break;
  8172.    case FLAG_SYMTYPE:
  8173.         flag   = (Fool)
  8174.                  NNMbbexp(np,bp,cmdp->cmd.scmd.ptreep,FLAG_SYMTYPE);
  8175.         if (!bp->runtime_error) {
  8176.           SETB(var,flag);
  8177.         }
  8178.         break;
  8179.    default:
  8180.         fprintf(np->batch_outfile,
  8181.                 "Set of %s failed due to unrecognized var type\n", var);
  8182.  }
  8183.  if (bp->runtime_error) {
  8184.    fprintf(np->batch_outfile,
  8185.            "Set of %s failed due to errors building value\n", var);
  8186.  }
  8187.  
  8188.  return; 
  8189. }
  8190.  
  8191. /****** Parse batch SET          command. ****************************/
  8192.  
  8193. struct newscmd *
  8194. NNMbpset(np,bp)
  8195. Rstruc nncb         *np;
  8196. Rstruc batch        *bp;
  8197. {
  8198.  struct newscmd     *cmdp       = NULL;
  8199.  struct ptree       *treep      = NULL;
  8200.  char               *var        = NULL;
  8201.  enum symtype        type;
  8202.  
  8203.  /* Next token must be variable name.  */
  8204.  
  8205.  if (!NNMbgtok(np,bp,TOKEN_READ)) return NULL;   /* get token */
  8206.  if (bp->curtok.type != WORD_TOKEN) {
  8207.    NNMbsynt(np,bp,NULL,0, "Expected SET variable name not seen");
  8208.    NNMbflus(np,bp);                         /* flush input tokens */
  8209.    return NULL;
  8210.  }
  8211.  
  8212.  var = NNMcopy(np,bp->curtok.string);
  8213.  
  8214.  /* Variable must have been declared, else it is not valid.  */
  8215.  
  8216.  if (!(type = (enum symtype)NNMbvget(np,bp,var,NO_SYMTYPE))) {
  8217.    NNMbsynt(np,bp,var,0,"Variable has not been declared");
  8218.    NNMbflus(np,bp);                         /* flush input tokens */
  8219.    return NULL;
  8220.  }
  8221.  
  8222.  /*
  8223.   * Next token must be either an equal sign or the first of a series
  8224.   * of "datums".  If the latter, assume the former was present.
  8225.   */
  8226.  
  8227.  if (!NNMbgtok(np,bp,TOKEN_PEEK)) return NULL;   /* Peek next token */
  8228.  if (bp->nextok.type == EQ_TOKEN) {
  8229.    (void)NNMbgtok(np,bp,TOKEN_FLUSH);            /* Eat the '=' */
  8230.  }
  8231.  
  8232.  /*
  8233.   * Rest of tokens define the string to which the variable must be set.
  8234.   * Note that the type (returned by NNMbvget) is the type of the
  8235.   * variable in question, defining the type of its value.
  8236.   */
  8237.  
  8238.  treep = NNMbgexp(np,bp,type);  /* Get structure describing data */
  8239.  
  8240.  if (!treep) {
  8241.    NNMbsynt(np,bp,NULL,0,"Bad arguments to SET, need '=' or data");
  8242.    return NULL;
  8243.  }
  8244.  
  8245.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for SET command");
  8246.  
  8247.  if (cmdp) {
  8248.    cmdp->mode = ANY_MODE;
  8249.    cmdp->proc = NNMbxset;
  8250.    cmdp->cmd.scmd.ptreep     = treep;
  8251.    cmdp->cmd.scmd.set_symbol = var;
  8252.    cmdp->cmd.scmd.set_type   = type;
  8253.  }
  8254.  
  8255.  return cmdp;
  8256. }
  8257.  
  8258. ./   ADD NAME=NNMBPVAR,SSI=01000001
  8259.  
  8260.  /********************************************************************/
  8261.  /*                                                                  */
  8262.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  8263.  /*                                                                  */
  8264.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  8265.  /* including the implied warranties of merchantability and fitness, */
  8266.  /* are expressly denied.                                            */
  8267.  /*                                                                  */
  8268.  /* Provided this copyright notice is included, this software may    */
  8269.  /* be freely distributed and not offered for sale.                  */
  8270.  /*                                                                  */
  8271.  /* Changes or modifications may be made and used only by the maker  */
  8272.  /* of same, and not further distributed.  Such modifications should */
  8273.  /* be mailed to the author for consideration for addition to the    */
  8274.  /* software and incorporation in subsequent releases.               */
  8275.  /*                                                                  */
  8276.  /********************************************************************/
  8277.  
  8278. /*=====================================================================
  8279.  *
  8280.  * Command: VARS
  8281.  *
  8282.  * Syntax:  VARS
  8283.  *
  8284.  * Mode:    any
  8285.  *
  8286.  * Function: Displays all defined variables and their types and values.
  8287.  *
  8288.  * Examples:  VARS
  8289.  *
  8290.  *====================================================================*/
  8291.  
  8292. #pragma  csect(code,  "NN@BPVAR")
  8293. #pragma  csect(static,"NN$BPVAR")
  8294. #include "nn.h"
  8295. #include "nnbatch.h"
  8296.  
  8297. /****** Dump variable name, type and value. **************************/
  8298.  
  8299. static void
  8300. dump_variable(np,bp,symp)
  8301. Rstruc nncb         *np;
  8302. Rstruc batch        *bp;
  8303. Rstruc symtab       *symp;
  8304. {
  8305.  
  8306.  if (!symp) return;
  8307.  
  8308.  fprintf(np->batch_outfile, " %-16.16s  ", symp->symvar);
  8309.  
  8310.  switch (symp->type) {
  8311.    case STRING_SYMTYPE:
  8312.         fprintf(np->batch_outfile, "STRING  %s\n", symp->symval);
  8313.         break;
  8314.    case NUMBER_SYMTYPE:
  8315.         fprintf(np->batch_outfile, "NUMBER  %d\n", symp->symnum);
  8316.         break;
  8317.    case FLAG_SYMTYPE:
  8318.         fprintf(np->batch_outfile, "FLAG    %s\n",
  8319.                 symp->symnum ? "TRUE" : "FALSE");
  8320.         break;
  8321.  }
  8322.  
  8323.  return; 
  8324. }
  8325.  
  8326. /****** Display variable. ********************************************/
  8327.  
  8328. static void
  8329. display_variable(np,bp,symp)
  8330. Rstruc nncb         *np;
  8331. Rstruc batch        *bp;
  8332. Rstruc symtab       *symp;
  8333. {
  8334.  
  8335.  if (!symp) return;
  8336.  
  8337.  if (symp->left) display_variable(np,bp,symp->left);
  8338.  dump_variable(np,bp,symp);
  8339.  if (symp->right) display_variable(np,bp,symp->right);
  8340.  
  8341.  return; 
  8342. }
  8343.  
  8344. /****** Execute batch VARS       command. ****************************/
  8345.  
  8346. static void
  8347. NNMbxvar(np,bp,cmdp)
  8348. Rstruc nncb         *np;
  8349. Rstruc batch        *bp;
  8350. Rstruc newscmd      *cmdp;
  8351. {
  8352.  
  8353.  fprintf(np->batch_outfile, "Current variables follow\n\n");
  8354.  display_variable(np,bp,bp->symtabp);
  8355.  fprintf(np->batch_outfile, "\nEnd variable display\n");
  8356.  
  8357.  return; 
  8358.  
  8359. }
  8360.  
  8361. /****** Parse batch VARS         command. ****************************/
  8362.  
  8363. struct newscmd *
  8364. NNMbpvar(np,bp)
  8365. Rstruc nncb         *np;
  8366. Rstruc batch        *bp;
  8367. {
  8368.  struct newscmd     *cmdp;
  8369.  
  8370.  bp->stop_at_newline = TRUE;
  8371.  
  8372.  NNMbtras(np,bp,"VARS");   /* Trash extraneous parameters */
  8373.  
  8374.  if (bp->syntax_error) return NULL;
  8375.  
  8376.  GETMAIN(cmdp, struct newscmd, 1, "newscmd for VARS command");
  8377.  
  8378.  if (cmdp) {
  8379.    cmdp->mode = ANY_MODE;
  8380.    cmdp->proc = NNMbxvar;
  8381.  }
  8382.  
  8383.  return cmdp;
  8384.  
  8385. }
  8386.  
  8387. ./   ADD NAME=NNMBSOUT,SSI=01020001
  8388.  
  8389.  /********************************************************************/
  8390.  /*                                                                  */
  8391.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  8392.  /*                                                                  */
  8393.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  8394.  /* including the implied warranties of merchantability and fitness, */
  8395.  /* are expressly denied.                                            */
  8396.  /*                                                                  */
  8397.  /* Provided this copyright notice is included, this software may    */
  8398.  /* be freely distributed and not offered for sale.                  */
  8399.  /*                                                                  */
  8400.  /* Changes or modifications may be made and used only by the maker  */
  8401.  /* of same, and not further distributed.  Such modifications should */
  8402.  /* be mailed to the author for consideration for addition to the    */
  8403.  /* software and incorporation in subsequent releases.               */
  8404.  /*                                                                  */
  8405.  /********************************************************************/
  8406.  
  8407. #pragma  csect(code,  "NN@BSOUT")
  8408. #pragma  csect(static,"NN$BSOUT")
  8409. #include "nn.h"
  8410. #include "nnbatch.h"
  8411.  
  8412. /****** Set the output file from the OUTFILE variable. ***************/
  8413.  
  8414. FILE *
  8415. NNMbsout(np,bp)
  8416. Rstruc nncb         *np;
  8417. Rstruc batch        *bp;
  8418. {
  8419.  char               *outfile;
  8420.  FILE               *outfp = NULL;
  8421.  FILE               *infp  = NULL;
  8422.  Bool                appending;
  8423.  
  8424.  outfile = GETC("OUTFILE");
  8425.  if (!outfile) outfile = "";
  8426.  if (bp->outfilename && EQUAL(bp->outfilename,outfile)) {
  8427.    if (!bp->outfp) outfp = np->batch_outfile;
  8428.    else outfp = bp->outfp;
  8429.  }
  8430.  else {
  8431.    if (bp->outfp) {
  8432.      if (fclose(bp->outfp) < 0) {
  8433.        fprintf(stderr,"Error closing outfile\n");
  8434.        bp->runtime_error = TRUE;
  8435.      }
  8436.      fprintf(np->batch_outfile,"Ending output to %s\n",bp->outfilename);
  8437.      bp->outfp = NULL;
  8438.      bp->outfilename = NULL;
  8439.    }
  8440.    if (*outfile) {
  8441.      if (TEST_IF_FILE_EXISTS(infp,outfile)) {
  8442.        CLEANUP_IF_FILE_EXISTS(infp);
  8443.        appending = TRUE;
  8444.      }
  8445.      else {
  8446.        appending = FALSE;
  8447.      }
  8448.      outfp = OPEN_OUTPUT_FILE_FOR_WRITE_OR_APPEND(outfile,appending);
  8449.      if (!outfp) {
  8450.        perror(outfile);
  8451.        fprintf(np->batch_outfile,"Error: OUTFILE %s is not usable.\n",
  8452.                                  outfile);
  8453.        bp->runtime_error = TRUE;
  8454.      }
  8455.      else {
  8456.        bp->outfp = outfp;
  8457.        bp->outfilename = NNMcopy(np,outfile);
  8458.        fprintf(np->batch_outfile,"Beginning output to %s\n", outfile);
  8459.      }
  8460.    }
  8461.    else {
  8462.      outfp = np->batch_outfile;
  8463.      bp->outfp = NULL;
  8464.      bp->outfilename = NULL;
  8465.    }
  8466.  }
  8467.  
  8468.  return outfp;
  8469. }
  8470.  
  8471. ./   ADD NAME=NNMBSYNT,SSI=01000013
  8472.  
  8473.  /********************************************************************/
  8474.  /*                                                                  */
  8475.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  8476.  /*                                                                  */
  8477.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  8478.  /* including the implied warranties of merchantability and fitness, */
  8479.  /* are expressly denied.                                            */
  8480.  /*                                                                  */
  8481.  /* Provided this copyright notice is included, this software may    */
  8482.  /* be freely distributed and not offered for sale.                  */
  8483.  /*                                                                  */
  8484.  /* Changes or modifications may be made and used only by the maker  */
  8485.  /* of same, and not further distributed.  Such modifications should */
  8486.  /* be mailed to the author for consideration for addition to the    */
  8487.  /* software and incorporation in subsequent releases.               */
  8488.  /*                                                                  */
  8489.  /********************************************************************/
  8490.  
  8491. #pragma  csect(code,  "NN@BSYNT")
  8492. #pragma  csect(static,"NN$BSYNT")
  8493. #include "nn.h"
  8494. #include "nnbatch.h"
  8495.  
  8496. /****** Syntax error. ************************************************/
  8497.  
  8498. void
  8499. NNMbsynt(np,bp,cp,len,msg)
  8500. Rstruc nncb         *np;
  8501. Rstruc batch        *bp;
  8502. char                *cp;
  8503. int                  len;
  8504. char                *msg;
  8505. {
  8506.  
  8507.  if (cp && len == 0) len = strlen(cp);
  8508.  if (!cp) {
  8509.    fprintf(np->batch_outfile, "Syntax error: %s.\n", msg);
  8510.  }
  8511.  else {
  8512.    fprintf(np->batch_outfile, "Syntax error: %s.  Token: %*.*s\n",
  8513.                               msg, len, len, cp);
  8514.  }
  8515.  
  8516.  bp->syntax_error = TRUE;
  8517.  bp->curtok.type  = ERROR_TOKEN;
  8518.  bp->nextok.type  = NO_TOKEN;
  8519.  bp->input_errors++;
  8520.  
  8521.  return; 
  8522. }
  8523.  
  8524. ./   ADD NAME=NNMBTEXT,SSI=01000037
  8525.  
  8526.  /********************************************************************/
  8527.  /*                                                                  */
  8528.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  8529.  /*                                                                  */
  8530.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  8531.  /* including the implied warranties of merchantability and fitness, */
  8532.  /* are expressly denied.                                            */
  8533.  /*                                                                  */
  8534.  /* Provided this copyright notice is included, this software may    */
  8535.  /* be freely distributed and not offered for sale.                  */
  8536.  /*                                                                  */
  8537.  /* Changes or modifications may be made and used only by the maker  */
  8538.  /* of same, and not further distributed.  Such modifications should */
  8539.  /* be mailed to the author for consideration for addition to the    */
  8540.  /* software and incorporation in subsequent releases.               */
  8541.  /*                                                                  */
  8542.  /********************************************************************/
  8543.  
  8544. #pragma  csect(code,  "NN@BTEXT")
  8545. #pragma  csect(static,"NN$BTEXT")
  8546. #include "nn.h"
  8547. #include "nnbatch.h"
  8548.  
  8549. /****** Print text lines. ********************************************/
  8550.  
  8551. static int
  8552. print_text_lines(np,bp,fp,textp,linep,extracting)
  8553. Rstruc nncb         *np;
  8554. Rstruc batch        *bp;
  8555. FILE                *fp;
  8556. struct textline     *textp;
  8557. char               **linep;
  8558. Fool                 extracting;
  8559. {
  8560.  struct textline    *tp;
  8561.  char               *cp;
  8562.  int                 l;
  8563.  int                 write_error;
  8564.  Bool                tab_expanding;
  8565.  Bool                appending;
  8566.  Bool                blank_before_separator;
  8567.  char               *separator_line;
  8568.  
  8569.  if (!fp) return TRUE;
  8570.  
  8571.  if (extracting) {
  8572.    tab_expanding           = np->extract_tab_expanding;
  8573.    appending               = np->extract_appending;
  8574.    blank_before_separator  = np->extract_blank_before_separator;
  8575.    separator_line          = np->extract_separator_line;
  8576.  }
  8577.  else {
  8578.    tab_expanding           = TRUE;
  8579.    appending               = FALSE;
  8580.    blank_before_separator  = FALSE;
  8581.    separator_line          = "";
  8582.  }
  8583.  
  8584.  tab_expanding = extracting ? np->extract_tab_expanding
  8585.                             : GETB("TABEXPAND");
  8586.  write_error   = 0;
  8587.  
  8588.  /* If append mode, and a separator line was specified, use it. */
  8589.  
  8590.  while (appending && separator_line && *separator_line) {
  8591.    if (fprintf(fp,"%s\n",separator_line) < 0) {
  8592.      *linep = separator_line;
  8593.      write_error = 1;
  8594.      break;
  8595.    }
  8596.    if (blank_before_separator) {
  8597.      if (fprintf(fp,"\n") < 0) {
  8598.        *linep = "<blank before separator>";
  8599.        write_error = 2;
  8600.        break;
  8601.      }
  8602.    }
  8603.    break;
  8604.  }
  8605.  
  8606.  for (tp=textp; tp && !write_error; tp=tp->next) {
  8607.    if (tp->text_length == 0) {
  8608.      if (fputc('\n',fp) == EOF) {
  8609.        *linep = "<single newline character>";
  8610.        write_error = 3;
  8611.        break;
  8612.      }
  8613.    }
  8614.    else if (tp->text_length > 0) {
  8615.      if (tab_expanding) {
  8616.        cp = tp->tab_expanded_text;
  8617.        l  = tp->tab_expanded_text_length;
  8618.      }
  8619.      else {
  8620.        cp = tp->text;
  8621.        l  = tp->text_length;
  8622.      }
  8623.      for (; l > 0; cp += 251, l -= 251) {
  8624.        fwrite(cp,(l>251 ? 251 : l),1,fp);
  8625.        if (ferror(fp)) {
  8626.          *linep = cp;
  8627.          write_error = 4;
  8628.          break;
  8629.        } 
  8630.        if (fputc('\n',fp) == EOF) {
  8631.          *linep = "<single newline character>";
  8632.          write_error = 5;
  8633.          break;
  8634.        } 
  8635.      }
  8636.    }
  8637.  }
  8638.  
  8639.  if (write_error) return write_error;
  8640.  if (ferror(fp)) {
  8641.    *linep = "<ferror occurred>";
  8642.    return -1;
  8643.  }
  8644.  else return 0;
  8645. }
  8646.  
  8647. /****** Process the lines of text retrieved from server. *************/
  8648.  
  8649. void
  8650. NNMbtext(np,thp,fp)
  8651. Rstruc nncb         *np;
  8652. struct texthdr      *thp;
  8653. FILE                *fp;
  8654. {
  8655.  Rstruc batch       *bp = np->batch_hook;
  8656.  int                 rc;
  8657.  char               *line;
  8658.  Fool                extracting;
  8659.  
  8660.  if (fp) {  /* file pointer passed :: called from EXTRACT command */
  8661.    extracting = TRUE;
  8662.  }
  8663.  else {
  8664.    fp = NNMbsout(np,bp);    /* set output file */
  8665.    extracting = FALSE;
  8666.  }
  8667.  
  8668.  rc = print_text_lines(np,bp,fp,thp->first_text_line,&line,extracting);
  8669.  if (rc != 0) {
  8670.    fprintf(stderr,"Error %d writing text to outfile\n",rc);
  8671.    fprintf(stderr,"Line: %s\n",line);
  8672.    bp->runtime_error = TRUE;
  8673.  }
  8674.  
  8675.  return; 
  8676.  
  8677. }
  8678.  
  8679. ./   ADD NAME=NNMBTRAS,SSI=01000033
  8680.  
  8681.  /********************************************************************/
  8682.  /*                                                                  */
  8683.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  8684.  /*                                                                  */
  8685.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  8686.  /* including the implied warranties of merchantability and fitness, */
  8687.  /* are expressly denied.                                            */
  8688.  /*                                                                  */
  8689.  /* Provided this copyright notice is included, this software may    */
  8690.  /* be freely distributed and not offered for sale.                  */
  8691.  /*                                                                  */
  8692.  /* Changes or modifications may be made and used only by the maker  */
  8693.  /* of same, and not further distributed.  Such modifications should */
  8694.  /* be mailed to the author for consideration for addition to the    */
  8695.  /* software and incorporation in subsequent releases.               */
  8696.  /*                                                                  */
  8697.  /********************************************************************/
  8698.  
  8699. #pragma  csect(code,  "NN@BTRAS")
  8700. #pragma  csect(static,"NN$BTRAS")
  8701. #include "nn.h"
  8702. #include "nnbatch.h"
  8703.  
  8704. /****** Trash extraneous data in command line. ***********************/
  8705.  
  8706. void
  8707. NNMbtras(np,bp,name)
  8708. Rstruc nncb         *np;
  8709. Rstruc batch        *bp;
  8710. char                *name;
  8711. {
  8712.  struct token       *tp;
  8713.  Bool                finished = FALSE;
  8714.  char                tmp[81];
  8715.  
  8716.  /*
  8717.   * Pull tokens until semicolon or EOF.  Note that EOL will not be
  8718.   * considered the end of the datum stream, because the user may wish
  8719.   * to specify a long list that takes several lines.  Therefore, an
  8720.   * explicit semicolon is required to terminate the list.
  8721.   */
  8722.  
  8723.  while (!finished && (tp = PEEK())) {
  8724.    switch (tp->type) {
  8725.      case EOL_TOKEN:
  8726.      case EOF_TOKEN:
  8727.      case SEMI_TOKEN: EAT();
  8728.                       finished = TRUE;
  8729.                       break;
  8730.      default:         EAT();
  8731.                       sprintf(tmp,"Extraneous data in %s command",name);
  8732.                       NNMbsynt(np,bp,tp->string,0,tmp);
  8733.                       break;
  8734.    }
  8735.  }
  8736.  
  8737.  return; 
  8738. }
  8739.  
  8740. ./   ADD NAME=NNMBVGET,SSI=01000041
  8741.  
  8742.  /********************************************************************/
  8743.  /*                                                                  */
  8744.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  8745.  /*                                                                  */
  8746.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  8747.  /* including the implied warranties of merchantability and fitness, */
  8748.  /* are expressly denied.                                            */
  8749.  /*                                                                  */
  8750.  /* Provided this copyright notice is included, this software may    */
  8751.  /* be freely distributed and not offered for sale.                  */
  8752.  /*                                                                  */
  8753.  /* Changes or modifications may be made and used only by the maker  */
  8754.  /* of same, and not further distributed.  Such modifications should */
  8755.  /* be mailed to the author for consideration for addition to the    */
  8756.  /* software and incorporation in subsequent releases.               */
  8757.  /*                                                                  */
  8758.  /********************************************************************/
  8759.  
  8760. #pragma  csect(code,  "NN@BVGET")
  8761. #pragma  csect(static,"NN$BVGET")
  8762. #include "nn.h"
  8763. #include "nnbatch.h"
  8764.  
  8765. /****** Report type mismatch error. **********************************/
  8766.  
  8767. static void
  8768. type_error(np,var,type1,type2)
  8769. Rstruc nncb     *np;
  8770. char            *var;
  8771. char            *type1;
  8772. char            *type2;
  8773. {
  8774.  
  8775.  ERR4("Type mismatch: \
  8776. Cannot retrieve a value of type %s from %s variable %s.",
  8777.       type1,type2,var);
  8778.  
  8779.  return; 
  8780.  
  8781. }
  8782.  
  8783. /****** Get a value from the symbol table. ***************************/
  8784.  
  8785. ANYTYPE
  8786. NNMbvget(np,bp,var,type)
  8787. Rstruc nncb         *np;
  8788. Rstruc batch        *bp;
  8789. char                *var;
  8790. enum symtype         type;
  8791. {
  8792.  Rstruc symtab      *symp;
  8793.  int                 varlen;
  8794.  char                vartest[MAX_SYMBOL_LENGTH];
  8795.  
  8796.  varlen = strlen(var);
  8797.  if (varlen < 1 || varlen > MAX_SYMBOL_LENGTH) {
  8798.    ERR2( 
  8799.     "A variable name must be between 1 and %d characters in length.",
  8800.         MAX_SYMBOL_LENGTH);
  8801.    return FALSE;
  8802.  }
  8803.  
  8804.  memset(vartest,'\0',MAX_SYMBOL_LENGTH);
  8805.  memcpy(vartest,var,varlen);
  8806.  
  8807.  symp = bp->symtabp;
  8808.  
  8809.  while (symp) {
  8810.    switch (memcmp(vartest, symp->symvar, MAX_SYMBOL_LENGTH)) {
  8811.      case 0:   /* equal   */
  8812.                break;
  8813.      case 1:   /* greater */
  8814.                symp = symp->right;
  8815.                continue;
  8816.      default:  /* less    */
  8817.                symp = symp->left;
  8818.                continue;
  8819.    }
  8820.    break;
  8821.  }
  8822.  
  8823.  /* Special case, just to see if the variable exists or not. */
  8824.  
  8825.  if (type == NO_SYMTYPE)
  8826.     return (symp ? (ANYTYPE)symp->type : (ANYTYPE)NO_SYMTYPE);
  8827.  
  8828.  if (!symp) {
  8829.    ERR2("The variable %s has not been declared or set to a value.",var);
  8830.    return NULL;
  8831.  }
  8832.  
  8833.  /*------------------------------------------------------------------*
  8834.   *                                                                  *
  8835.   * Table of allowable type-to-type settings:                        *
  8836.   *                                                                  *
  8837.   * symp->type |   type      | result                                *
  8838.   *____________|_____________|_________________________________      *
  8839.   * STRING     |   STRING    | OK                                    *
  8840.   *            |   NUMBER    | error                                 *
  8841.   *            |   FLAG      | error                                 *
  8842.   *____________|_____________|_________________________________      *
  8843.   * NUMBER     |   STRING    | convert to string via sprintf %d      *
  8844.   *            |   NUMBER    | OK                                    *
  8845.   *            |   FLAG      | interpret as nonzero or zero          *
  8846.   *____________|_____________|_________________________________      *
  8847.   * FLAG       |   STRING    | convert to "1" or "0"                 *
  8848.   *            |   NUMBER    | convert to 1 or 0                     *
  8849.   *            |   FLAG      | OK                                    *
  8850.   *            |             |                                       *
  8851.   *------------------------------------------------------------------*/
  8852.  
  8853.  switch (symp->type) {
  8854.    case STRING_SYMTYPE:
  8855.         switch (type) {
  8856.           case STRING_SYMTYPE: return (ANYTYPE)symp->symval;
  8857.  
  8858.           case NUMBER_SYMTYPE: type_error(np,var,"NUMBER","STRING");
  8859.                                break;
  8860.           case FLAG_SYMTYPE:   type_error(np,var,"FLAG","STRING");
  8861.                                break;
  8862.         }
  8863.         break;
  8864.    case NUMBER_SYMTYPE:
  8865.         switch (type) {
  8866.           case STRING_SYMTYPE: sprintf(symp->symval,"%d",symp->symnum);
  8867.                                return (ANYTYPE)symp->symval;
  8868.  
  8869.           case NUMBER_SYMTYPE: return (ANYTYPE)symp->symnum;
  8870.  
  8871.           case FLAG_SYMTYPE:   return (symp->symnum
  8872.                                        ? (ANYTYPE)1 : (ANYTYPE)0);
  8873.  
  8874.         }
  8875.         break;
  8876.    case FLAG_SYMTYPE:
  8877.         switch (type) {
  8878.           case STRING_SYMTYPE: return (symp->symnum
  8879.                                        ? (ANYTYPE)"1" : (ANYTYPE)"0");
  8880.  
  8881.           case NUMBER_SYMTYPE: return (symp->symnum
  8882.                                        ? (ANYTYPE)1 : (ANYTYPE)0);
  8883.  
  8884.           case FLAG_SYMTYPE:   return (symp->symnum
  8885.                                        ? (ANYTYPE)1 : (ANYTYPE)0);
  8886.  
  8887.         }
  8888.         break;
  8889.  }
  8890.  
  8891.  return NULL;
  8892. }
  8893.  
  8894. ./   ADD NAME=NNMBVPUT,SSI=01000021
  8895.  
  8896.  /********************************************************************/
  8897.  /*                                                                  */
  8898.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  8899.  /*                                                                  */
  8900.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  8901.  /* including the implied warranties of merchantability and fitness, */
  8902.  /* are expressly denied.                                            */
  8903.  /*                                                                  */
  8904.  /* Provided this copyright notice is included, this software may    */
  8905.  /* be freely distributed and not offered for sale.                  */
  8906.  /*                                                                  */
  8907.  /* Changes or modifications may be made and used only by the maker  */
  8908.  /* of same, and not further distributed.  Such modifications should */
  8909.  /* be mailed to the author for consideration for addition to the    */
  8910.  /* software and incorporation in subsequent releases.               */
  8911.  /*                                                                  */
  8912.  /********************************************************************/
  8913.  
  8914. #pragma  csect(code,  "NN@BVPUT")
  8915. #pragma  csect(static,"NN$BVPUT")
  8916. #include "nn.h"
  8917. #include "nnbatch.h"
  8918.  
  8919. /****** Report type mismatch error. **********************************/
  8920.  
  8921. static void
  8922. type_error(np,var,type1,type2)
  8923. Rstruc nncb     *np;
  8924. char            *var;
  8925. char            *type1;
  8926. char            *type2;
  8927. {
  8928.  
  8929.  ERR4("Type mismatch: \
  8930. Cannot assign a value of type %s to %s variable %s.",
  8931.       type1,type2,var);
  8932.  
  8933.  return; 
  8934.  
  8935. }
  8936.  
  8937. /****** Set value of symbol table entry. *****************************/
  8938.  
  8939. static void
  8940. set_value(np,sp,var,val,type)
  8941. Rstruc nncb     *np;
  8942. struct symtab   *sp;
  8943. char            *var;
  8944. ANYTYPE          val;
  8945. enum symtype     type;
  8946. {
  8947.  
  8948.  /*------------------------------------------------------------------*
  8949.   *                                                                  *
  8950.   * Table of allowable type-to-type settings:                        *
  8951.   *                                                                  *
  8952.   * sp->type   |   type      | result                                *
  8953.   *____________|_____________|_________________________________      *
  8954.   * STRING     |   STRING    | OK                                    *
  8955.   *            |   NUMBER    | convert to string via sprintf %d      *
  8956.   *            |   FLAG      | error                                 *
  8957.   *____________|_____________|_________________________________      *
  8958.   * NUMBER     |   STRING    | error                                 *
  8959.   *            |   NUMBER    | OK                                    *
  8960.   *            |   FLAG      | convert to 1 or 0                     *
  8961.   *____________|_____________|_________________________________      *
  8962.   * FLAG       |   STRING    | error                                 *
  8963.   *            |   NUMBER    | interpret as nonzero or zero          *
  8964.   *            |   FLAG      | OK                                    *
  8965.   *            |             |                                       *
  8966.   *------------------------------------------------------------------*/
  8967.  
  8968.  switch (sp->type) {
  8969.    case STRING_SYMTYPE:
  8970.         switch (type) {
  8971.           case STRING_SYMTYPE: strcpy(sp->symval,(char *)val);
  8972.                                break;
  8973.           case NUMBER_SYMTYPE: sprintf(sp->symval,"%d",(int)val);
  8974.                                break;
  8975.           case FLAG_SYMTYPE:   type_error(np,var,"FLAG","STRING");
  8976.                                break;
  8977.         }
  8978.         break;
  8979.    case NUMBER_SYMTYPE:
  8980.         switch (type) {
  8981.           case STRING_SYMTYPE: type_error(np,var,"STRING","NUMBER");
  8982.                                break;
  8983.           case NUMBER_SYMTYPE: sp->symnum = (int)val;
  8984.                                break;
  8985.           case FLAG_SYMTYPE:   sp->symnum = (Fool)val ? 1 : 0;
  8986.                                break;
  8987.         }
  8988.         break;
  8989.    case FLAG_SYMTYPE:
  8990.         switch (type) {
  8991.           case STRING_SYMTYPE: type_error(np,var,"STRING","FLAG");
  8992.                                break;
  8993.           case NUMBER_SYMTYPE: sp->symnum = (int)val ? 1 : 0;
  8994.                                break;
  8995.           case FLAG_SYMTYPE:   sp->symnum = (Fool)val ? 1 : 0;
  8996.                                break;
  8997.         }
  8998.         break;
  8999.  }
  9000.  
  9001.  if (np->debug_file) {
  9002.    switch (sp->type) {
  9003.      case STRING_SYMTYPE:  fprintf(np->debug_file,
  9004.                                    "NNMbvput: %s set to '%s'\n",
  9005.                                    sp->symvar, sp->symval);
  9006.                            break;
  9007.      case NUMBER_SYMTYPE:  fprintf(np->debug_file,
  9008.                                    "NNMbvput: %s set to %d\n",
  9009.                                    sp->symvar, sp->symnum);
  9010.                            break;
  9011.      case FLAG_SYMTYPE:    fprintf(np->debug_file,
  9012.                                    "NNMbvput: %s set to %s\n",
  9013.                                    sp->symvar,
  9014.                                    sp->symnum ? "TRUE" : "FALSE");
  9015.                            break;
  9016.    }
  9017.  }
  9018.  
  9019.  return; 
  9020. }
  9021.  
  9022. /****** Put a value into the symbol table. ***************************/
  9023.  
  9024. void
  9025. NNMbvput(np,bp,var,type,val)
  9026. Rstruc nncb         *np;
  9027. Rstruc batch        *bp;
  9028. char                *var;
  9029. enum symtype         type;
  9030. ANYTYPE              val;
  9031. {
  9032.  Rstruc symtab      *symp;
  9033.  Rstruc symtab     **sympref;
  9034.  struct symtab      *sympnew;
  9035.  struct symtab      *sympleft;
  9036.  struct symtab      *sympright;
  9037.  enum symtype        symptype;
  9038.  int                 varlen;
  9039.  int                 minimum_value_length;
  9040.  int                 getlen;
  9041.  int                 comp;
  9042.  Bool                symbol_found;
  9043.  char                vartest[MAX_SYMBOL_LENGTH];
  9044.  
  9045.  varlen = strlen(var);
  9046.  if (varlen < 1 || varlen > MAX_SYMBOL_LENGTH) {
  9047.    ERR2( 
  9048.     "A variable name must be between 1 and %d characters in length.",
  9049.         MAX_SYMBOL_LENGTH);
  9050.    return;
  9051.  }
  9052.  
  9053.  memset(vartest,'\0',MAX_SYMBOL_LENGTH);
  9054.  memcpy(vartest,var,varlen);
  9055.  
  9056.  switch (type) {
  9057.    case STRING_SYMTYPE: minimum_value_length = strlen((char *)val) + 1;
  9058.                         break;
  9059.    case NUMBER_SYMTYPE: minimum_value_length = 12;
  9060.                         break;
  9061.    case FLAG_SYMTYPE:   minimum_value_length = 6;
  9062.                         break;
  9063.  }
  9064.  
  9065.  symbol_found = FALSE;
  9066.  
  9067.  sympleft  = NULL;
  9068.  sympright = NULL;
  9069.  sympref   = &bp->symtabp;
  9070.  
  9071.  while ((symp=*sympref)) {
  9072.    switch ((comp=memcmp(vartest, symp->symvar, MAX_SYMBOL_LENGTH))) {
  9073.      case 0:   /* equal   */
  9074.                symbol_found = TRUE;
  9075.                /* free this entry and allocate a new one if this one
  9076.                   is too small to hold the requested value */
  9077.                if (minimum_value_length > symp->vallen) {
  9078.                  symptype  = symp->type;
  9079.                  sympleft  = symp->left;
  9080.                  sympright = symp->right;
  9081.                  FREEMAIN(*sympref,"old symbol table entry");
  9082.                  *sympref = NULL;
  9083.                  break;
  9084.                }
  9085.                else {
  9086.                  set_value(np,symp,var,val,type);
  9087.                  return;
  9088.                }
  9089.      case 1:   /* greater */
  9090.                sympref = &symp->right;
  9091.                continue;
  9092.      default:  /* less    */
  9093.                sympref = &symp->left;
  9094.                continue;
  9095.    }
  9096.  }
  9097.  
  9098.  /* Symbol not found - not allowed, means variable not declared */
  9099.  
  9100.  if (!symbol_found) {
  9101.    ERR2("The variable %s has not been declared or set to a value.",var);
  9102.    return;
  9103.  }
  9104.  
  9105.  getlen = offsetof(struct symtab, symval) + minimum_value_length;
  9106.  
  9107.  GETMAIN(sympnew, char, getlen, "new symbol table entry");
  9108.  if (!sympnew) {
  9109.    ERR2("Cannot set variable: \
  9110. Unable to allocate storage to hold value for variable %s.",
  9111.         var);
  9112.    return;
  9113.  }
  9114.  
  9115.  memcpy(sympnew->symvar, vartest, MAX_SYMBOL_LENGTH);
  9116.  sympnew->left   = sympleft;
  9117.  sympnew->right  = sympright;
  9118.  sympnew->vallen = minimum_value_length;
  9119.  sympnew->type   = symptype;
  9120.  *sympref        = sympnew;
  9121.  
  9122.  set_value(np,sympnew,var,val,type);
  9123.  
  9124.  return; 
  9125.  
  9126. }
  9127.  
  9128. ./   ADD NAME=NNMBXFAR,SSI=01040032
  9129.  
  9130.  /********************************************************************/
  9131.  /*                                                                  */
  9132.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  9133.  /*                                                                  */
  9134.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  9135.  /* including the implied warranties of merchantability and fitness, */
  9136.  /* are expressly denied.                                            */
  9137.  /*                                                                  */
  9138.  /* Provided this copyright notice is included, this software may    */
  9139.  /* be freely distributed and not offered for sale.                  */
  9140.  /*                                                                  */
  9141.  /* Changes or modifications may be made and used only by the maker  */
  9142.  /* of same, and not further distributed.  Such modifications should */
  9143.  /* be mailed to the author for consideration for addition to the    */
  9144.  /* software and incorporation in subsequent releases.               */
  9145.  /*                                                                  */
  9146.  /********************************************************************/
  9147.  
  9148. #pragma  csect(code,  "NN@BXFAR")
  9149. #pragma  csect(static,"NN$BXFAR")
  9150. #include "nn.h"
  9151. #include "nnbatch.h"
  9152.  
  9153. /****** Execute batch FOR articles command. **************************/
  9154.  
  9155. struct variablesave {
  9156.                      int        number;
  9157.                      Bool       read;
  9158.                      Bool       missing;
  9159.                      char      *subject;
  9160.                      char      *date;
  9161.                      char      *from;
  9162.                      char      *messageid;
  9163.                     };
  9164.  
  9165. /****** Set article variables. ***************************************/
  9166.  
  9167. static void
  9168. set_article_variables(np,bp,vp,anum,vsp)
  9169. Rstruc nncb                 *np;
  9170. Rstruc batch                *bp;
  9171. VARK                        *vp;
  9172. int                          anum;
  9173. struct variablesave         *vsp;
  9174. {
  9175.  Rstruc newsarticle         *ap = VARK2PARTICLE(*vp);
  9176.  
  9177.  vsp->number     = GETA("NUMBER");
  9178.  vsp->read       = GETB("READ");
  9179.  vsp->missing    = GETB("MISSING");
  9180.  vsp->subject    = NNMcopy(np,GETC("SUBJECT"));
  9181.  vsp->date       = NNMcopy(np,GETC("DATE"));
  9182.  vsp->from       = NNMcopy(np,GETC("FROM"));
  9183.  vsp->messageid  = NNMcopy(np,GETC("MESSAGEID"));
  9184.  
  9185.  SETA("NUMBER",       anum);
  9186.  SETB("READ",         IsRead(*vp));
  9187.  if (IsMissing(*vp)) {
  9188.    SETB("MISSING",    TRUE);
  9189.    SETC("SUBJECT",    "");
  9190.    SETC("DATE",       "");
  9191.    SETC("FROM",       "");
  9192.    SETC("MESSAGEID",  "");
  9193.  }
  9194.  else {
  9195.    SETB("MISSING",    FALSE);
  9196.    SETC("SUBJECT",    ap->subject);
  9197.    SETC("DATE",       ap->date);
  9198.    SETC("FROM",       ap->from);
  9199.    SETC("MESSAGEID",  ap->message_id);
  9200.  }
  9201.  
  9202.  return ;
  9203. }
  9204.  
  9205. /****** Unset article variables. *************************************/
  9206.  
  9207. static void
  9208. unset_article_variables(np,bp,vsp)
  9209. Rstruc nncb                 *np;
  9210. Rstruc batch                *bp;
  9211. struct variablesave         *vsp;
  9212. {
  9213.  
  9214.  SETA("NUMBER",    vsp->number);
  9215.  SETB("READ",      vsp->read);
  9216.  SETB("MISSING",   vsp->missing);
  9217.  SETC("SUBJECT",   vsp->subject);
  9218.  SETC("DATE",      vsp->date);
  9219.  SETC("FROM",      vsp->from);
  9220.  SETC("MESSAGEID", vsp->messageid);
  9221.  
  9222.  FREEMAIN(vsp->subject,   "saved copy of SUBJECT");
  9223.  FREEMAIN(vsp->date,      "saved copy of DATE");
  9224.  FREEMAIN(vsp->from,      "saved copy of FROM");
  9225.  FREEMAIN(vsp->messageid, "saved copy of MESSAGEID");
  9226.  
  9227.  return; 
  9228. }
  9229.  
  9230. /****** Reset newsgroup variables. ***********************************/
  9231.  
  9232. static void
  9233. reset_newsgroup_variables(np,bp,gp)
  9234. Rstruc nncb                 *np;
  9235. Rstruc batch                *bp;
  9236. Rstruc newsgroup            *gp;
  9237. {
  9238.  
  9239.  SETA("COUNT"      ,gp->article_count);
  9240.  SETA("UNREAD"     ,gp->unread_count);
  9241.  SETA("FIRST"      ,gp->low_number);
  9242.  SETA("LAST"       ,gp->high_number);
  9243.  
  9244.  return ;
  9245. }
  9246.  
  9247. /****** Execute article commands. ************************************/
  9248.  
  9249. static void
  9250. execute_article_commands(np,bp,vp,treep)
  9251. Rstruc nncb                 *np;
  9252. Rstruc batch                *bp;
  9253. VARK                        *vp;
  9254. struct cmdtree              *treep;
  9255. {
  9256.  VARK                       *savevp;
  9257.  
  9258.  for (; treep; treep = treep->next) {
  9259.    bp->runtime_error = FALSE;
  9260.    savevp = bp->vp;
  9261.    bp->vp = vp;
  9262.    (treep->cmd->proc) (np,bp,treep->cmd);
  9263.    bp->vp = savevp;
  9264.    SETB("ERROR",bp->runtime_error);
  9265.  }
  9266.  
  9267.  return; 
  9268. }
  9269.  
  9270. /****** Test if article passes filter. *****************************/
  9271.  
  9272. static Bool
  9273. pass_filter(np,bp,filter)
  9274. Rstruc nncb                 *np;
  9275. Rstruc batch                *bp;
  9276. struct ptree                *filter;
  9277. {
  9278.  Bool                        passes_filter;
  9279.  
  9280.  if (filter) {
  9281.    passes_filter = (Fool)NNMbbexp(np,bp,filter,FLAG_SYMTYPE);
  9282.    if (bp->runtime_error) {
  9283.      bp->request_errors++;
  9284.      passes_filter = FALSE;
  9285.    }
  9286.  }
  9287.  else passes_filter = TRUE;
  9288.  
  9289.  return passes_filter;
  9290. }
  9291.  
  9292. /****** Test if article passes criterion. ****************************/
  9293.  
  9294. static Bool
  9295. pass_criterion(np,bp,vp,anum,which,first,last)
  9296. Rstruc nncb                 *np;
  9297. Rstruc batch                *bp;
  9298. VARK                        *vp;
  9299. int                          anum;
  9300. enum which_articles          which;
  9301. struct ptree                *first;
  9302. struct ptree                *last;
  9303. {
  9304.  int                         firstnum;
  9305.  int                         lastnum;
  9306.  
  9307.  switch (which) {
  9308.    case ALL_ARTICLES:
  9309.             return TRUE;
  9310.    case READ_ARTICLES:
  9311.             return (IsRead(*vp));
  9312.    case UNREAD_ARTICLES:
  9313.             return (IsUnread(*vp));
  9314.    case RANGED_ARTICLES:
  9315.             if (first)
  9316.                  firstnum = (int)NNMbbexp(np,bp,first,NUMBER_SYMTYPE);
  9317.             else firstnum = FIRST_ARTICLE_IN_RANGE;
  9318.             if (last)
  9319.                  lastnum  = (int)NNMbbexp(np,bp,last, NUMBER_SYMTYPE);
  9320.             else lastnum  = firstnum;
  9321.             return (anum >= firstnum && anum <= lastnum);
  9322.    case NO_ARTICLES:
  9323.             return FALSE;
  9324.    default:
  9325.             return FALSE;
  9326.  }
  9327.  
  9328. }
  9329.  
  9330. /****** Execute batch FOR articles command. **************************/
  9331.  
  9332. void
  9333. NNMbxfar(np,bp,cmdp)
  9334. Rstruc nncb                 *np;
  9335. Rstruc batch                *bp;
  9336. Rstruc newscmd              *cmdp;
  9337. {
  9338.  Rstruc newsgroup           *gp;
  9339.  Rstruc newsarticle         *ap;
  9340.  VARK                       *vp;
  9341.  struct ptree               *filter;
  9342.  struct cmdtree             *treep;
  9343.  struct ptree               *first;
  9344.  struct ptree               *last;
  9345.  int                         anum;
  9346.  enum which_articles         which;
  9347.  struct variablesave         varsave;
  9348.  
  9349.  filter = cmdp->cmd.ncmd.fors.filter;
  9350.  treep  = cmdp->cmd.ncmd.fors.treep;
  9351.  which  = cmdp->cmd.ncmd.fors.crit.which;
  9352.  first  = cmdp->cmd.ncmd.fors.crit.first;
  9353.  last   = cmdp->cmd.ncmd.fors.crit.last;
  9354.  
  9355.  gp = bp->gp;
  9356.  
  9357.  /* Logic:  (1) apply "which" criteria
  9358.   *         (2) set variables for articles remaining
  9359.   *         (3) apply filters
  9360.   * Rationale:  Variables must be set before filters can use them.
  9361.   *             But criteria can be used to reduce the load.
  9362.   */
  9363.  
  9364.  np->current_newsgroup   = gp;
  9365.  np->newsgroup_selected  = FALSE;
  9366.  
  9367.  if (!GroupSelected(gp)) gp = NNMdng(np,gp,NULL);
  9368.  if (!gp) return;
  9369.  
  9370.  bp->gp = gp;
  9371.  reset_newsgroup_variables(np,bp,gp);
  9372.  if (gp->article_vector) {
  9373.    for (anum = gp->vector_first; anum <= gp->vector_last; anum++) {
  9374.      vp = &GETVARK(gp,anum);
  9375.      if (pass_criterion(np,bp,vp,anum,which,first,last)) {
  9376.        if (NNMrarh(np,gp,vp,anum,NULL)) { /* retrieve article hdr */
  9377.          set_article_variables(np,bp,vp,anum,&varsave);
  9378.          if (pass_filter(np,bp,filter)) {
  9379.            execute_article_commands(np,bp,vp,treep);
  9380.          }
  9381.          unset_article_variables(np,bp,&varsave);
  9382.        } 
  9383.      }
  9384.    }
  9385.  }
  9386.  
  9387.  np->current_newsgroup  = NULL;
  9388.  np->newsgroup_selected = FALSE;
  9389.  
  9390.  return; 
  9391. }
  9392.  
  9393. ./   ADD NAME=NNMBXFNG,SSI=01040010
  9394.  
  9395.  /********************************************************************/
  9396.  /*                                                                  */
  9397.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  9398.  /*                                                                  */
  9399.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  9400.  /* including the implied warranties of merchantability and fitness, */
  9401.  /* are expressly denied.                                            */
  9402.  /*                                                                  */
  9403.  /* Provided this copyright notice is included, this software may    */
  9404.  /* be freely distributed and not offered for sale.                  */
  9405.  /*                                                                  */
  9406.  /* Changes or modifications may be made and used only by the maker  */
  9407.  /* of same, and not further distributed.  Such modifications should */
  9408.  /* be mailed to the author for consideration for addition to the    */
  9409.  /* software and incorporation in subsequent releases.               */
  9410.  /*                                                                  */
  9411.  /********************************************************************/
  9412.  
  9413. #pragma  csect(code,  "NN@BXFNG")
  9414. #pragma  csect(static,"NN$BXFNG")
  9415. #include "nn.h"
  9416. #include "nnbatch.h"
  9417.  
  9418. struct variablesave {
  9419.                      char      *group;
  9420.                      Bool       registered;
  9421.                      Bool       newgroup;
  9422.                      Bool       nosuchgroup;
  9423.                      int        count;
  9424.                      int        unread;
  9425.                      int        first;
  9426.                      int        last;
  9427.                     };
  9428.  
  9429. /****** Set newsgroup variables. *************************************/
  9430.  
  9431. static void
  9432. set_newsgroup_variables(np,bp,gp,vsp)
  9433. Rstruc nncb                 *np;
  9434. Rstruc batch                *bp;
  9435. Rstruc newsgroup            *gp;
  9436. struct variablesave         *vsp;
  9437. {
  9438.  
  9439.  vsp->group       = NNMcopy(np,GETC("GROUP"));
  9440.  vsp->registered  = GETB("REGISTERED");
  9441.  vsp->newgroup    = GETB("NEWGROUP");
  9442.  vsp->nosuchgroup = GETB("NOSUCHGROUP");
  9443.  vsp->count       = GETA("COUNT");
  9444.  vsp->unread      = GETA("UNREAD");
  9445.  vsp->first       = GETA("FIRST");
  9446.  vsp->last        = GETA("LAST");
  9447.  
  9448.  SETC("GROUP"      ,gp->name);
  9449.  SETA("COUNT"      ,gp->article_count);
  9450.  SETA("UNREAD"     ,gp->unread_count);
  9451.  SETA("FIRST"      ,gp->low_number);
  9452.  SETA("LAST"       ,gp->high_number);
  9453.  SETB("REGISTERED" ,(gp->registered > 0) ? TRUE : FALSE);
  9454.  
  9455.  if (NewGroup(gp)) {  /* if new newsgroup */
  9456.    fprintf(np->batch_outfile,"New newsgroup: %s (%d articles)\n",
  9457.                              gp->name, gp->article_count);
  9458.    gp->registered = -1;
  9459.    SETB("NEWGROUP",TRUE);
  9460.  }
  9461.  else if (gp->registered == -1) {  /* old way: if new newsgroup */
  9462.    fprintf(np->batch_outfile,"New newsgroup: %s (%d articles)\n",
  9463.                              gp->name, gp->article_count);
  9464.    SetNewGroup(gp);
  9465.    SETB("NEWGROUP",TRUE);
  9466.  }
  9467.  else {
  9468.    OffNewGroup(gp);
  9469.    SETB("NEWGROUP",FALSE);
  9470.  }
  9471.  
  9472.  if (BogusGroup(gp)) {
  9473.    fprintf(np->batch_outfile,"Nonexistent newsgroup: %s\n", gp->name);
  9474.    SetNoSuchGroup(gp);
  9475.    SETB("NOSUCHGROUP",TRUE);
  9476.  }
  9477.  else {
  9478.    SETB("NOSUCHGROUP",FALSE);
  9479.  }
  9480.  
  9481.  return ;
  9482. }
  9483.  
  9484. /****** Unset newsgroup variables. **********************************/
  9485.  
  9486. static void
  9487. unset_newsgroup_variables(np,bp,gp,vsp)
  9488. Rstruc nncb                 *np;
  9489. Rstruc batch                *bp;
  9490. Rstruc newsgroup            *gp;
  9491. struct variablesave         *vsp;
  9492. {
  9493.  
  9494.  SETC("GROUP"       ,vsp->group);
  9495.  SETB("REGISTERED"  ,vsp->registered);
  9496.  SETB("NEWGROUP"    ,vsp->newgroup);
  9497.  SETB("NOSUCHGROUP" ,vsp->nosuchgroup);
  9498.  SETA("COUNT"       ,vsp->count);
  9499.  SETA("UNREAD"      ,vsp->unread);
  9500.  SETA("FIRST"       ,vsp->first);
  9501.  SETA("LAST"        ,vsp->last);
  9502.  
  9503.  FREEMAIN(vsp->group,"saved copy of GROUP");
  9504.  
  9505.  return ;
  9506. }
  9507.  
  9508. /****** See if new newsgroup. ****************************************/
  9509.  
  9510. static void
  9511. see_if_new_newsgroup(np,bp,gp)
  9512. Rstruc nncb                 *np;
  9513. Rstruc batch                *bp;
  9514. Rstruc newsgroup            *gp;
  9515. {
  9516.  
  9517.  if (NewGroup(gp)) {  /* if new newsgroup */
  9518.  
  9519.    if (GETB("AUTOREGISTER")) {
  9520.      gp->registered = 1;
  9521.      SETB("REGISTERED",TRUE);
  9522.      fprintf(np->batch_outfile,
  9523.             "Added newsgroup %s as REGISTERED\n", gp->name);
  9524.    }
  9525.    else {
  9526.      gp->registered = 0;
  9527.      SETB("REGISTERED",FALSE);
  9528.      fprintf(np->batch_outfile,
  9529.             "Added newsgroup %s as UNREGISTERED\n", gp->name);
  9530.    }
  9531.  }
  9532.  
  9533.  return; 
  9534. }
  9535.  
  9536. /****** See if bogus newsgroup. **************************************/
  9537.  
  9538. static void
  9539. see_if_bogus_newsgroup(np,bp,gp)
  9540. Rstruc nncb                 *np;
  9541. Rstruc batch                *bp;
  9542. Rstruc newsgroup            *gp;
  9543. {
  9544.  
  9545.  if (BogusGroup(gp)) {
  9546.  
  9547.    if (GETB("AUTODELETE")) {
  9548.      SetNoSuchGroup(gp);
  9549.      OffGroupListed(gp);
  9550.      fprintf(np->batch_outfile, "Deleted newsgroup %s\n", gp->name);
  9551.    }
  9552.    else {
  9553.      SetGroupListed(gp);
  9554.      fprintf(np->batch_outfile, "Kept newsgroup %s\n", gp->name);
  9555.    }
  9556.  }
  9557.  
  9558.  return; 
  9559. }
  9560.  
  9561. /****** Execute newsgroup commands. **********************************/
  9562.  
  9563. static void
  9564. execute_newsgroup_commands(np,bp,gp,treep)
  9565. Rstruc nncb                 *np;
  9566. Rstruc batch                *bp;
  9567. Rstruc newsgroup            *gp;
  9568. struct cmdtree              *treep;
  9569. {
  9570.  struct newsgroup           *savegp;
  9571.  
  9572.  for (; treep; treep = treep->next) {
  9573.    bp->runtime_error = FALSE;
  9574.    savegp = bp->gp;
  9575.    bp->gp = gp;
  9576.    (treep->cmd->proc) (np,bp,treep->cmd);
  9577.    bp->gp = savegp;
  9578.    SETB("ERROR",bp->runtime_error);
  9579.  }
  9580.  
  9581.  return; 
  9582. }
  9583.  
  9584. /****** Test if newsgroup passes filter. *****************************/
  9585.  
  9586. static Bool
  9587. pass_filter(np,bp,gp,filter)
  9588. Rstruc nncb                 *np;
  9589. Rstruc batch                *bp;
  9590. Rstruc newsgroup            *gp;
  9591. struct ptree                *filter;
  9592. {
  9593.  Bool                        passes_filter;
  9594.  
  9595.  if (filter) {
  9596.    passes_filter = (Fool)NNMbbexp(np,bp,filter,FLAG_SYMTYPE);
  9597.    if (bp->runtime_error) {
  9598.      bp->request_errors++;
  9599.      passes_filter = FALSE;
  9600.    }
  9601.  }
  9602.  else passes_filter = TRUE;
  9603.  
  9604.  return passes_filter;
  9605.  
  9606. }
  9607.  
  9608. /****** Match group name against group string. ***********************/
  9609.  
  9610. static Bool
  9611. match(name,string)
  9612. char    *name;
  9613. char    *string;
  9614. {
  9615.  
  9616.  return FALSE;
  9617. }
  9618.  
  9619. /****** See if group name is in group string. ************************/
  9620.  
  9621. static Bool
  9622. in(name,string)
  9623. char    *name;
  9624. char    *string;
  9625. {
  9626.  char   *s;
  9627.  char   *cp1;
  9628.  char   *cp2;
  9629.  char   *cp3;
  9630.  
  9631.  s = string;
  9632.  for (;;) {
  9633.    cp1 = strstr(s,name);
  9634.    if (!cp1) return FALSE;
  9635.    cp2 = cp1-1;
  9636.    if (cp2 < string || *cp2 == ' ' || *cp2 == '\t' || *cp2 == ',') {
  9637.      cp3 = cp1+strlen(name);
  9638.      if (*cp3 == '\0' || *cp3 == ' ' || *cp3 == '\t' || *cp3 == ',') {
  9639.        return TRUE;
  9640.      }
  9641.    }
  9642.    s = cp1 + 1;
  9643.    continue;
  9644.  }
  9645. }
  9646.  
  9647. /****** Test if newsgroup passes criterion. **************************/
  9648.  
  9649. static Bool
  9650. pass_criterion(np,bp,gp,which,groups)
  9651. Rstruc nncb                 *np;
  9652. Rstruc batch                *bp;
  9653. Rstruc newsgroup            *gp;
  9654. enum which_newsgroups        which;
  9655. struct ptree                *groups;
  9656. {
  9657.  char                       *groupstring;
  9658.  
  9659.  if (groups) {
  9660.    groupstring = NNMbbexp(np,bp,groups,STRING_SYMTYPE);
  9661.    lowercase_in_place(groupstring);
  9662.  }
  9663.  
  9664.  switch (which) {
  9665.    case ALL_NEWSGROUPS:           return TRUE;
  9666.    case REGISTERED_NEWSGROUPS:    return (gp->registered >  0);
  9667.    case UNREGISTERED_NEWSGROUPS:  return (gp->registered == 0);
  9668.    case NAMED_NEWSGROUPS:         return in(gp->name,groupstring);
  9669.    case MASKED_NEWSGROUPS:
  9670.  fprintf(np->batch_outfile,"Sorry, cannot handle MASKED_NEWSGROUPS.\n");
  9671.                                   return match(gp->name,groupstring);
  9672.    case NO_NEWSGROUPS:            return FALSE;
  9673.    default:                       return FALSE;
  9674.  }
  9675.  
  9676. }
  9677.  
  9678. /****** Execute batch FOR newsgroups command. ************************/
  9679.  
  9680. void
  9681. NNMbxfng(np,bp,cmdp)
  9682. Rstruc nncb                 *np;
  9683. Rstruc batch                *bp;
  9684. Rstruc newscmd              *cmdp;
  9685. {
  9686.  Rstruc newsgroup           *gp;
  9687.  struct ptree               *filter;
  9688.  struct cmdtree             *treep;
  9689.  struct ptree               *groups;
  9690.  enum which_newsgroups       which;
  9691.  struct variablesave         varsave;
  9692.  Bool                        serverlist;
  9693.  
  9694.  filter = cmdp->cmd.icmd.fors.filter;
  9695.  treep  = cmdp->cmd.icmd.fors.treep;
  9696.  which  = cmdp->cmd.icmd.fors.crit.which;
  9697.  groups = cmdp->cmd.icmd.fors.crit.groups;
  9698.  
  9699.  /* Connect to server. */
  9700.  
  9701.  if (!NNMbconn(np,bp)) {
  9702.    fprintf(np->batch_outfile,"No newsgroup commands executed.\n");
  9703.    bp->request_errors++;
  9704.    return;
  9705.  }
  9706.  
  9707.  /* Determine source of newsgroups - SERVER or NEWSRC. */
  9708.  /* If SERVERLIST is true, do an NNTP list.  Otherwise */
  9709.  /* use NEWSRC and do individual group requests...     */
  9710.  
  9711.  /* If we do get the newsgroups via LIST, do it only once. */
  9712.  
  9713.  serverlist = GETB("SERVERLIST");
  9714.  
  9715.  if (serverlist) {
  9716.    if (!bp->newsgroups_retrieved) {
  9717.      if (!NNMdlang(np,LIST_ALL)) { /* get list of all grps fr server */
  9718.        fprintf(np->batch_outfile,"No newsgroups processed.\n");
  9719.        bp->request_errors++;
  9720.        return;
  9721.      }
  9722.      bp->newsgroups_retrieved = TRUE;
  9723.    }
  9724.  }
  9725.  
  9726.  /* Logic:  (1) apply "which" criteria
  9727.   *         (2) set variables for groups remaining
  9728.   *         (3) apply filters
  9729.   * Rationale:  Variables must be set before filters can use them.
  9730.   *             But criteria can be used to reduce the load.
  9731.   */
  9732.  
  9733.  /* The list of newsgroups has already been built from newsrc at this
  9734.   * point.  Now, if the source is the server, then ask NNTP to get
  9735.   * the current list of newsgroups and process it against the list
  9736.   * from NEWSRC.  If the source is NEWSRC, then get the current status
  9737.   * of each newsgroup via the NNTP "group" command (slow).
  9738.   */
  9739.  
  9740.  /* Note that the position of see_if_new_newsgroup determines if new
  9741.   * newsgroups are to be registered depending on AUTOREGISTER *after*
  9742.   * the filtering or *before*.  If *after*, then all groups that are
  9743.   * not handled get autoregistered as DEREGISTERED.
  9744.   */
  9745.  
  9746.  for (gp = np->first_newsgroup; gp; gp = gp->next) {
  9747.    if (pass_criterion(np,bp,gp,which,groups)) {
  9748.      if (!serverlist) {
  9749.        NNMdng(np,gp,NULL);             /* do newsgroup by address */
  9750.        if (np->newsgroup_not_found) {
  9751.          SetNoSuchGroup(gp);
  9752.          gp->article_count = 0;
  9753.          gp->unread_count  = 0;
  9754.        } 
  9755.      }
  9756.      set_newsgroup_variables(np,bp,gp,&varsave);
  9757.      if (pass_filter(np,bp,gp,filter)) {
  9758.        see_if_new_newsgroup(np,bp,gp);
  9759.        see_if_bogus_newsgroup(np,bp,gp);
  9760.        if (!NoSuchGroup(gp)) {
  9761.          execute_newsgroup_commands(np,bp,gp,treep);
  9762.        } 
  9763.      }
  9764.      unset_newsgroup_variables(np,bp,gp,&varsave);
  9765.    }
  9766.  }
  9767.  
  9768.  return; 
  9769. }
  9770.  
  9771. ./   ADD NAME=NNMCAR,SSI=010C0008
  9772.  
  9773.  /********************************************************************/
  9774.  /*                                                                  */
  9775.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  9776.  /*                                                                  */
  9777.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  9778.  /*                                                                  */
  9779.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  9780.  /* including the implied warranties of merchantability and fitness, */
  9781.  /* are expressly denied.                                            */
  9782.  /*                                                                  */
  9783.  /* Provided this copyright notice is included, this software may    */
  9784.  /* be freely distributed and not offered for sale.                  */
  9785.  /*                                                                  */
  9786.  /* Changes or modifications may be made and used only by the maker  */
  9787.  /* of same, and not further distributed.  Such modifications should */
  9788.  /* be mailed to the author for consideration for addition to the    */
  9789.  /* software and incorporation in subsequent releases.               */
  9790.  /*                                                                  */
  9791.  /********************************************************************/
  9792.  
  9793. #pragma  csect(code,  "NN@CAR  ")
  9794. #pragma  csect(static,"NN$CAR  ")
  9795. #include "nn.h"
  9796.  
  9797. /****** Choose article (Determine if it is eligible for display) *****/
  9798.  
  9799. Bool
  9800. NNMcar(np,gp,anum,vp,app,cdp,carfun)
  9801. Rstruc nncb           *np;
  9802. Rstruc newsgroup      *gp;
  9803. int                    anum;
  9804. VARK                  *vp;
  9805. struct newsarticle   **app;
  9806. struct countdown      *cdp;
  9807. enum choose_reason     carfun;
  9808. {
  9809.  Rstruc newsarticle   *ap = NULL;
  9810.  Bool                  rc = FALSE;
  9811.  
  9812.  /* If vp is null, anum must be nonzero.
  9813.   * If vp is provided, anum may be zero, in which case NNMrarh will
  9814.   * figure out what it is if it needs to.  Not to worry here.
  9815.   */
  9816.  
  9817.  if (!vp) vp = &GETVARK(gp,anum);
  9818.  
  9819.  if (IsUnknown(*vp)) {
  9820.    if (np->show_all_articles        /* if "A"ll requested           */
  9821.     || IsUnread(*vp)                /* or "S" and article not read  */
  9822.     || (!np->unread_articles_only   /* or article already in table  */
  9823.         && IsPresent(*vp)
  9824.         && (ap=VARK2PARTICLE(*vp)) && ArticleRetrieved(ap))) {
  9825.      if (*np->article_only_string) {
  9826.        SetKnownIneligible(*vp);
  9827.        if (!ap) ap = NNMrarh(np,gp,vp,anum,cdp);
  9828.        if (ap && IsPresent(*vp)) {
  9829.          if (NNMstrlc(ap->subject,np->article_only_string)) {
  9830.            SetKnownEligible(*vp);
  9831.            rc = TRUE;
  9832.          }
  9833.        } 
  9834.      }
  9835.      else {                      /* no ONLY string */
  9836.        if (carfun != MARK_ONLY) {
  9837.          SetKnownIneligible(*vp);
  9838.          if (!ap) ap = NNMrarh(np,gp,vp,anum,cdp);
  9839.          if (ap && IsPresent(*vp)) {
  9840.            SetKnownEligible(*vp);
  9841.            rc = TRUE;
  9842.          }
  9843.        } 
  9844.        else {
  9845.          ap = VARK2PARTICLE(*vp);
  9846.          if (ap != V_NULL_ARTICLE && ap != V_MISSING_ARTICLE) {
  9847.            rc = TRUE;  /* just return for marking, don't set up etc. */
  9848.          }
  9849.        } 
  9850.      }
  9851.    }
  9852.    else SetKnownIneligible(*vp);
  9853.  }
  9854.  
  9855.  if (IsEligible(*vp)) {
  9856.    rc = TRUE;
  9857.    if (!ap) ap = VARK2PARTICLE(*vp);
  9858.  }
  9859.  
  9860.  if (rc && app) *app = ap;
  9861.  return rc;
  9862. }
  9863.  
  9864. ./   ADD NAME=NNMCLRNG,SSI=01020039
  9865.  
  9866.  /********************************************************************/
  9867.  /*                                                                  */
  9868.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  9869.  /*                                                                  */
  9870.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  9871.  /* including the implied warranties of merchantability and fitness, */
  9872.  /* are expressly denied.                                            */
  9873.  /*                                                                  */
  9874.  /* Provided this copyright notice is included, this software may    */
  9875.  /* be freely distributed and not offered for sale.                  */
  9876.  /*                                                                  */
  9877.  /* Changes or modifications may be made and used only by the maker  */
  9878.  /* of same, and not further distributed.  Such modifications should */
  9879.  /* be mailed to the author for consideration for addition to the    */
  9880.  /* software and incorporation in subsequent releases.               */
  9881.  /*                                                                  */
  9882.  /********************************************************************/
  9883.  
  9884. #pragma  csect(code,  "NN@CLRNG")
  9885. #pragma  csect(static,"NN$CLRNG")
  9886. #include "nn.h"
  9887.  
  9888. /****** Clear newsgroups. ********************************************/
  9889.  
  9890. void
  9891. NNMclrng(np)
  9892. Rstruc nncb           *np;
  9893. {
  9894.  Rstruc newsgroup     *gp1;
  9895.  Rstruc newsgroup     *gp2;
  9896.  VARK                 *vp;
  9897.  VARK                 *vpfirst;
  9898.  VARK                 *vplast;
  9899.  
  9900.  np->newsgroup_selected = FALSE;
  9901.  np->new_newsgroup_count = 0;
  9902.  
  9903.  gp1 = np->first_newsgroup;
  9904.  while (gp1) {
  9905.   gp2 = gp1->next;
  9906.   if (gp1->article_vector) {
  9907.     vpfirst = &GETVARKFIRST(gp1);
  9908.     vplast  = &GETVARKLAST(gp1);
  9909.     for (vp = vpfirst; vp <= vplast; vp++) {
  9910.       if (IsPresent(*vp)) {
  9911.         NNMclrtx(np,VARK2PARTICLE(*vp));
  9912.       }
  9913.     }
  9914.   }
  9915.   FREEMAIN(gp1->sort_vector,        "newsgroup sort vector");
  9916.   FREEMAIN(gp1->article_vector,     "newsgroup article vector");
  9917.   if (gp1->saved_newsrc_line != gp1->saved_newsrc_data) {
  9918.     FREEMAIN(gp1->saved_newsrc_line,"newsgroup newsrc line");
  9919.   }
  9920.   FREEMAIN(gp1,                     "newsgroup");
  9921.   gp1 = gp2;
  9922.  }
  9923.  
  9924.  np->first_newsgroup      = NULL;
  9925.  np->first_newsgroup_alt  = NULL;
  9926.  np->current_newsgroup    = NULL;
  9927.  np->last_newsgroup       = NULL;
  9928.  np->last_added_newsgroup = NULL;
  9929.  
  9930.  return; 
  9931. }
  9932.  
  9933. ./   ADD NAME=NNMCLRTX,SSI=01000048
  9934.  
  9935.  /********************************************************************/
  9936.  /*                                                                  */
  9937.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  9938.  /*                                                                  */
  9939.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  9940.  /* including the implied warranties of merchantability and fitness, */
  9941.  /* are expressly denied.                                            */
  9942.  /*                                                                  */
  9943.  /* Provided this copyright notice is included, this software may    */
  9944.  /* be freely distributed and not offered for sale.                  */
  9945.  /*                                                                  */
  9946.  /* Changes or modifications may be made and used only by the maker  */
  9947.  /* of same, and not further distributed.  Such modifications should */
  9948.  /* be mailed to the author for consideration for addition to the    */
  9949.  /* software and incorporation in subsequent releases.               */
  9950.  /*                                                                  */
  9951.  /********************************************************************/
  9952.  
  9953. #pragma  csect(code,  "NN@CLRTX")
  9954. #pragma  csect(static,"NN$CLRTX")
  9955. #include "nn.h"
  9956.  
  9957. /****** Clear text. **************************************************/
  9958.  
  9959. void
  9960. NNMclrtx(np,ap)
  9961. Rstruc nncb           *np;
  9962. Rstruc newsarticle    *ap;
  9963.  
  9964. {
  9965.  Rstruc texthdr       *thp;
  9966.  Rstruc textline      *tp1;
  9967.  Rstruc textline      *tp2;
  9968.  
  9969.  /* If article is not specified, use main nncb, else article's text */
  9970.  
  9971.  thp = (ap ? &ap->thdr : &np->thdr);
  9972.  
  9973.  tp1 = thp->first_text_line;
  9974.  while (tp1) {
  9975.   tp2 = tp1->next;
  9976.   FREEMAIN(tp1,"text line");
  9977.   tp1 = tp2;
  9978.  }
  9979.  
  9980.  thp->text_body_line    = NULL;
  9981.  thp->first_text_line   = NULL;
  9982.  thp->current_text_line = NULL;
  9983.  thp->last_text_line    = NULL;
  9984.  thp->text_line_count   = 0;
  9985.  thp->text_max_length   = 0;
  9986.  thp->text_max_tab_expanded_length   = 0;
  9987.  
  9988.  return; 
  9989.  
  9990. }
  9991.  
  9992. ./   ADD NAME=NNMCNRF,SSI=01030011
  9993.  
  9994.  /********************************************************************/
  9995.  /*                                                                  */
  9996.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  9997.  /*                                                                  */
  9998.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  9999.  /*                                                                  */
  10000.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10001.  /* including the implied warranties of merchantability and fitness, */
  10002.  /* are expressly denied.                                            */
  10003.  /*                                                                  */
  10004.  /* Provided this copyright notice is included, this software may    */
  10005.  /* be freely distributed and not offered for sale.                  */
  10006.  /*                                                                  */
  10007.  /* Changes or modifications may be made and used only by the maker  */
  10008.  /* of same, and not further distributed.  Such modifications should */
  10009.  /* be mailed to the author for consideration for addition to the    */
  10010.  /* software and incorporation in subsequent releases.               */
  10011.  /*                                                                  */
  10012.  /********************************************************************/
  10013.  
  10014. #pragma  csect(code,  "NN@CNRF ")
  10015. #pragma  csect(static,"NN$CNRF ")
  10016. #include "nn.h"
  10017.  
  10018. /*** Write to newsrc file. *******************************************/
  10019.  
  10020. static Bool
  10021. write_to_newsrc(np,newsrc_line,thing)
  10022. Rstruc nncb        *np;
  10023. char               *newsrc_line;
  10024. char               *thing;
  10025. {
  10026.  char              *newlinep;
  10027.  Bool               write_ok = TRUE;
  10028.  
  10029.  if (!*thing) return TRUE;
  10030.  
  10031.  newlinep = strchr(thing,'\n');
  10032.  if (newlinep) {
  10033.    while (newlinep) {
  10034.      strncat(newsrc_line,thing,newlinep-thing);
  10035.      if (fprintf(np->newsrc_file,"%s\n",newsrc_line) < 0)
  10036.          write_ok = FALSE;
  10037.      strcpy(newsrc_line,"");
  10038.      thing = newlinep + 1;
  10039.      newlinep = strchr(thing,'\n');
  10040.    }
  10041.    strcat(newsrc_line,thing);
  10042.    return write_ok;
  10043.  }
  10044.  
  10045.  if (strlen(newsrc_line) + strlen(thing) > 250) {
  10046.    if (fprintf(np->newsrc_file,"%s\n",newsrc_line) < 0)
  10047.        write_ok = FALSE;
  10048.    strcpy(newsrc_line," ");
  10049.  }
  10050.  strcat(newsrc_line,thing);
  10051.  return write_ok;
  10052. }
  10053.  
  10054. /****** Close NEWSRC file. *******************************************/
  10055.  
  10056. void
  10057. NNMcnrf(np,what_to_open,updating)
  10058. Rstruc nncb         *np;
  10059. char                *what_to_open;
  10060. Fool                 updating;
  10061. {
  10062.  Rstruc newsgroup   *gp1;
  10063.  int                 newsrc_unread;
  10064.  int                 newsrc_topnum;
  10065.  int                 newsrc_count;
  10066.  register int        iv;
  10067.  int                 read0;
  10068.  int                 read1;
  10069.  int                 read2;
  10070.  int                 read3;
  10071.  Bool                write_ok;
  10072.  char                newsrc_line[257];
  10073.  char                newsrc_numb[32];
  10074.  
  10075.  write_ok = TRUE;
  10076.  
  10077.  /* If the file is currently open for input, close it first. */
  10078.  
  10079.  if (np->newsrc_file) {
  10080.    if (fclose(np->newsrc_file) < 0) {
  10081.      fprintf(stderr,"%s: Error closing NEWSRC file\n",what_to_open);
  10082.    }
  10083.    np->newsrc_file = NULL;
  10084.  }
  10085.  
  10086.  if (!updating) return;
  10087.  
  10088.  /* Open the file for output.  This will empty it at first. */
  10089.  
  10090.  if (!what_to_open) what_to_open = np->newsrc_to_open;
  10091.  
  10092.  np->newsrc_file = fopen(what_to_open,"w");
  10093.  if (np->newsrc_file == NULL) {
  10094.    perror("Cannot open NEWSRC file");
  10095.    return;
  10096.  }
  10097.  
  10098.  if (np->update_rewriting_newsrc) {
  10099.    if (!np->batch_mode) {
  10100.      (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  10101.      (void)NNMispf(np,"DISPLAY PANEL(NNMLUNRC)");
  10102.    }
  10103.  }
  10104.  
  10105.  /* Write current status into the file. */
  10106.  
  10107.  /********************************************************************/
  10108.  /*                                                                  */
  10109.  /* Note:  The format used here is designed to be compatible with    */
  10110.  /*        the format used by ANU-NEWS.  This is not an attempt to   */
  10111.  /*        duplicate the "look and feel" of ANU-NEWS - it is just    */
  10112.  /*        to be compatible with the saved state of VAX NEWS users.  */
  10113.  /*                                                                  */
  10114.  /********************************************************************/
  10115.  
  10116.  /* First record: time of last update in hex, current newsgroup, blah */
  10117.  
  10118.  if (fprintf(np->newsrc_file,"%.6s %.6s %s\n",
  10119.             np->lastNGdate, np->lastNGtime,
  10120.             np->current_newsgroup ? np->current_newsgroup->name : " ")
  10121.      < 0) write_ok = FALSE;
  10122.  
  10123.  for (gp1=np->first_newsgroup; gp1; gp1=gp1->next) {
  10124.  
  10125.    if (!NoSuchGroup(gp1)) { /* Skip groups that don't really exist */
  10126.  
  10127.     /* for each newsgroup, the following data...
  10128.      * newsgroupname: (registration) [unread,topnum] read-items
  10129.      *
  10130.      * if extended format, topnum = low_number":"high_number
  10131.      * otherwise topnum = high_number
  10132.      */
  10133.  
  10134.      /*    write out gp1->low_number somewhere too? */
  10135.  
  10136.      newsrc_unread = MAX(gp1->unread_count,0);
  10137.      newsrc_topnum = gp1->high_number;
  10138.      newsrc_count  = gp1->article_count;
  10139.  
  10140.      /* The following is a hack for "new newsgroups" */
  10141.      if (gp1->registered < 0) gp1->registered = 0;
  10142.  
  10143.      sprintf(newsrc_line,"%s: (%d) [%d,%d]",
  10144.           /* groupname */    gp1->name,
  10145.           /* reg/prio  */    gp1->registered,
  10146.           /* unread    */    newsrc_unread,
  10147.           /* topnum    */    newsrc_topnum);
  10148.  
  10149.  /*
  10150.   * All articles from 1 to low_number - 1 are "read" (expired, etc.)
  10151.   * If there is an article vector,
  10152.   *  All articles from 1 to vector_first - 1 are "read"
  10153.   *  All articles from vector_last + 1 to high_number are "read"
  10154.   * end
  10155.   */
  10156.  
  10157.      if (gp1->article_vector == NULL
  10158.       && gp1->saved_newsrc_line != NULL) {
  10159.        strcat(newsrc_line," ");
  10160.        if (!write_to_newsrc(np,newsrc_line,gp1->saved_newsrc_line))
  10161.            write_ok = FALSE;
  10162.      }
  10163.      else
  10164.      if (gp1->article_vector == NULL
  10165.    /* || newsrc_unread == newsrc_count */
  10166.       || newsrc_unread == (gp1->vector_last - gp1->vector_first + 1)) {
  10167.        sprintf(newsrc_numb, " <%d", gp1->low_number - 1);
  10168.        strcat(newsrc_line, newsrc_numb);
  10169.      }
  10170.      else {
  10171.        read0 = MAX(gp1->vector_first, gp1->low_number);
  10172.        read1 = 0;
  10173.        read2 = 0;
  10174.        read3 = gp1->vector_last;
  10175.        iv = read0;
  10176.        if (IsUnread(GETVARK(gp1,iv))) {
  10177.          sprintf(newsrc_numb, " <%d", read0 - 1);
  10178.          strcat(newsrc_line, newsrc_numb);
  10179.        } 
  10180.        while (iv <= read3) {
  10181.          /* look for the first of a series of read articles */
  10182.          while (iv <= read3 && IsUnread(GETVARK(gp1,iv))) iv++;
  10183.          read1 = iv;
  10184.          /* look for the last of a series of read articles */
  10185.          while (iv <= read3 && IsRead(GETVARK(gp1,iv))) iv++;
  10186.          read2 = iv-1;
  10187.          if (read2 == read3) read2 = gp1->high_number;
  10188.          if (read1 == read0)         sprintf(newsrc_numb," <%d",read2);
  10189.          else if (read1 >  read2)    *newsrc_numb = '\0';
  10190.          else if (read1 == read2)    sprintf(newsrc_numb," %d" ,read2);
  10191.          else if (read1 == read2-1)
  10192.                             sprintf(newsrc_numb," %d %d", read1,read2);
  10193.          else               sprintf(newsrc_numb," |%d=%d",read1,read2);
  10194.          if (!write_to_newsrc(np,newsrc_line,newsrc_numb))
  10195.              write_ok = FALSE;
  10196.        } 
  10197.      }
  10198.      if (*newsrc_line) {
  10199.        if (fprintf(np->newsrc_file,"%s\n",newsrc_line) < 0)
  10200.            write_ok = FALSE;
  10201.      }
  10202.    }
  10203.  }
  10204.  
  10205.  /* Close the file, saving the contents. */
  10206.  
  10207.  if (!write_ok || ferror(np->newsrc_file)) {
  10208.    fprintf(stderr,
  10209.            "%s: Error writing NEWSRC file.  Contents may be invalid.\n",
  10210.            what_to_open);
  10211.  }
  10212.  
  10213.  if (fclose(np->newsrc_file) < 0) {
  10214.    fprintf(stderr,
  10215.            "%s: Error closing NEWSRC file.  Contents may be invalid.\n",
  10216.            what_to_open);
  10217.  }
  10218.  np->newsrc_file = NULL;
  10219.  
  10220.  return; 
  10221. }
  10222.  
  10223. ./   ADD NAME=NNMCONN,SSI=01030039
  10224.  
  10225.  /********************************************************************/
  10226.  /*                                                                  */
  10227.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10228.  /*                                                                  */
  10229.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10230.  /* including the implied warranties of merchantability and fitness, */
  10231.  /* are expressly denied.                                            */
  10232.  /*                                                                  */
  10233.  /* Provided this copyright notice is included, this software may    */
  10234.  /* be freely distributed and not offered for sale.                  */
  10235.  /*                                                                  */
  10236.  /* Changes or modifications may be made and used only by the maker  */
  10237.  /* of same, and not further distributed.  Such modifications should */
  10238.  /* be mailed to the author for consideration for addition to the    */
  10239.  /* software and incorporation in subsequent releases.               */
  10240.  /*                                                                  */
  10241.  /********************************************************************/
  10242.  
  10243. #pragma  csect(code,  "NN@CONN ")
  10244. #pragma  csect(static,"NN$CONN ")
  10245. #include "nn.h"
  10246.  
  10247. /****** Internet address formatter. **********************************/
  10248.  
  10249. static void
  10250. format_ip_address(ia,is)
  10251. IPADDRESS   ia;
  10252. char       *is;
  10253. {
  10254.  char *cp = (char *)&ia;
  10255.  
  10256.  sprintf(is,"%d.%d.%d.%d",*cp,*(cp+1),*(cp+2),*(cp+3));
  10257.  return; 
  10258. }
  10259.  
  10260. /****** Connect to news server. **************************************/
  10261.  
  10262. Bool
  10263. NNMconn(np)
  10264. Rstruc nncb *np;
  10265. {
  10266.  char              *lp;
  10267.  struct hostent    *server_hp;
  10268.  struct sockaddr_in bindsock;       /* socket used by bind           */
  10269.  struct sockaddr_in consock;        /* socket used by connect        */
  10270.  int                bindsocklen;    /* size of bind socket           */
  10271.  int                consocklen;     /* size of connect socket        */
  10272.  int                bindrc;         /* the return code from bind     */
  10273.  int                connrc;         /* the return code from connect  */
  10274.  int                ip_part_1;
  10275.  int                ip_part_2;
  10276.  int                ip_part_3;
  10277.  int                ip_part_4;
  10278.  
  10279.  if (np->connected_to_server) {
  10280.    NNMdisc(np);                /* Disconnect from news server */
  10281.  }
  10282.  
  10283.  np->closing_connection = FALSE;
  10284.  
  10285.  if (!*np->nnserver) {
  10286.    ERR1("Server not defined;\
  10287. An NNTP server name must be defined before a connection can be made."
  10288.        );
  10289.    return FALSE;
  10290.  }
  10291.  
  10292.  uppercase_in_place(np->nnserver);
  10293.  
  10294.  /* Get server name and address.
  10295.   * The client name and address were gotten in NNMmain.
  10296.   */
  10297.  
  10298.  if (strchr(np->nnserver,'.') &&
  10299.      np->nnserver[strspn(np->nnserver,".0123456789")] == '\0') {
  10300.    ip_part_1 = ip_part_2 = ip_part_3 = ip_part_4 = 32767;
  10301.    strcpy(np->server_hostname, np->nnserver);
  10302.    sscanf(np->nnserver,"%d.%d.%d.%d",&ip_part_1,
  10303.                                      &ip_part_2,
  10304.                                      &ip_part_3,
  10305.                                      &ip_part_4);
  10306.    if (ip_part_1 > 255 ||
  10307.        ip_part_2 > 255 ||
  10308.        ip_part_3 > 255 ||
  10309.        ip_part_4 > 255) {
  10310.      ERR2("Syntax error in server network address: %s", np->nnserver);
  10311.      return FALSE;
  10312.    }
  10313.    np->server_ip_address = (IPADDRESS) ((ip_part_1 << 24) +
  10314.                                         (ip_part_2 << 16) +
  10315.                                         (ip_part_3 <<  8) +
  10316.                                         (ip_part_4      ));
  10317.  }
  10318.  else {
  10319.    server_hp = gethostbyname(np->nnserver);
  10320.    if (!server_hp) {
  10321.      ERR2(
  10322. "Unknown host %s - gethostbyname() could not resolve the server name.",
  10323.           np->nnserver);
  10324.      return FALSE;
  10325.    }
  10326.    strcpy(np->server_hostname, server_hp->h_name);
  10327.    np->server_ip_address = *(IPADDRESS *)server_hp->h_addr;
  10328.  }
  10329.  
  10330.  format_ip_address(np->server_ip_address, np->server_ip_addrstr);
  10331.  format_ip_address(np->client_ip_address, np->client_ip_addrstr);
  10332.  
  10333.  if (!np->batch_mode) {
  10334.    (void)NNMivput(np,"NNSERVER ",np->nnserver,-1);
  10335.    (void)NNMivput(np,"NNSERVIP ",np->server_ip_addrstr,-1);
  10336.    (void)NNMivput(np,"NNCLIENT ",np->nnclient,-1);
  10337.    (void)NNMivput(np,"NNCLIEIP ",np->client_ip_addrstr,-1);
  10338.  }
  10339.  
  10340.  consock.sin_family       = AF_INET;
  10341.  consock.sin_port         = htons(NNTP_PORT_NUMBER);
  10342.  consock.sin_addr.s_addr  = np->server_ip_address;
  10343.  
  10344.  bindsock.sin_family      = AF_INET;
  10345.  bindsock.sin_port        = 0;
  10346.  bindsock.sin_addr.s_addr = np->client_ip_address;
  10347.  
  10348.  np->socknum = socket(AF_INET, SOCK_STREAM, 0);
  10349.  if (np->socknum < 0) {
  10350.    REPORT_TCP_ERROR(np->nnserver);
  10351.    ERR2("TCP/IP error: socket() failed to make socket for server %s.",
  10352.         np->nnserver);
  10353.    return FALSE;
  10354.  }
  10355.  
  10356.  bindsocklen = sizeof(bindsock);
  10357.  bindrc = Bind(np->socknum, &bindsock, bindsocklen);
  10358.  if (bindrc < 0) {
  10359.    REPORT_TCP_ERROR(np->nnserver);
  10360.    ERR2("TCP/IP error: bind() failed to bind socket for server %s.",
  10361.         np->nnserver);
  10362.    return FALSE;
  10363.  }
  10364.  
  10365.  if (np->batch_mode) {
  10366.    fprintf(np->batch_outfile,
  10367.            "Client %s (%s) connecting to news server on %s (%s)\n",
  10368.            np->client_hostname, np->client_ip_addrstr,
  10369.            np->server_hostname, np->server_ip_addrstr);
  10370.  }
  10371.  else {
  10372.    (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  10373.    (void)NNMispf(np,"DISPLAY PANEL(NNMLCONN)");
  10374.  }
  10375.  
  10376.  if (np->debug_file) {
  10377.    fprintf(np->debug_file,
  10378.            "Client %s (%s) connecting to news server on %s (%s)\n",
  10379.            np->client_hostname, np->client_ip_addrstr,
  10380.            np->server_hostname, np->server_ip_addrstr);
  10381.  }
  10382.  
  10383.  consocklen = sizeof(consock);
  10384.  connrc = Connect(np->socknum, &consock, consocklen);
  10385.  
  10386.  if (connrc < 0) {
  10387.    REPORT_TCP_ERROR(np->nnserver);
  10388.    ERR2("TCP/IP failure: connect() failed to connect to server %s.",
  10389.         np->nnserver);
  10390.    return FALSE;
  10391.  }
  10392.  
  10393.  np->connected_to_server = TRUE;
  10394.  np->time_to_go_home     = FALSE;
  10395.  np->connection_broken   = FALSE;
  10396.  np->xhdr_not_available  = FALSE;
  10397.  
  10398.  /* Now that the connection has been established, the news server
  10399.   * is trying to send the first message:
  10400.   * "200 servername blah blah blah - posting allowed"
  10401.   * or
  10402.   * "201 servername blah blah blah - no posting allowed"
  10403.   * or
  10404.   * "502 servername won't talk to you - goodbye"
  10405.   * Receive that message.  Otherwise disconnect will fail.
  10406.   *
  10407.   * Read initial message from server.
  10408.   */
  10409.  
  10410.  for (;;) {
  10411.  
  10412.    NNMssrvr(np);                             /* Start server read */
  10413.  
  10414.    if (!NNMgsrvl(np,&lp)) return FALSE;      /* Get server line */
  10415.  
  10416.    switch (np->nntp_message_num) {
  10417.      case 200: np->posting_allowed = TRUE;   break;
  10418.      case 201: np->posting_allowed = FALSE;  break;
  10419.      case 502: NNMrperr(np);                /* Report procotol error */
  10420.                np->connection_broken = TRUE;
  10421.                NNMdisc(np);                 /* Clean up connection   */
  10422.                return FALSE;                /* and abandon attempt   */
  10423.     default:   NNMrperr(np);                /* Report protocol error */
  10424.                continue;                    /* and ignore bad data   */
  10425.    }
  10426.  
  10427.    break;
  10428.  
  10429.  }
  10430.  
  10431.  /* Clean up any other responses from server. */
  10432.  
  10433.  NNMesrvr(np);                             /* End server read */
  10434.  
  10435.  /* If server needs authorization, try to provide it.  Note that we
  10436.   * currently do this even on a reconnect.  A future optimization
  10437.   * could be to save the authorization info so that we don't have
  10438.   * to retrieve it all over again - as long as we don't retain
  10439.   * sensitive information in memory across ISPF displays.
  10440.   */
  10441.  
  10442.  if (NNMauth(np)) return TRUE;                 /* Send authinfo */
  10443.  else return FALSE;
  10444.  
  10445. }
  10446.  
  10447. ./   ADD NAME=NNMCOPY,SSI=01000006
  10448.  
  10449.  /********************************************************************/
  10450.  /*                                                                  */
  10451.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10452.  /*                                                                  */
  10453.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10454.  /* including the implied warranties of merchantability and fitness, */
  10455.  /* are expressly denied.                                            */
  10456.  /*                                                                  */
  10457.  /* Provided this copyright notice is included, this software may    */
  10458.  /* be freely distributed and not offered for sale.                  */
  10459.  /*                                                                  */
  10460.  /* Changes or modifications may be made and used only by the maker  */
  10461.  /* of same, and not further distributed.  Such modifications should */
  10462.  /* be mailed to the author for consideration for addition to the    */
  10463.  /* software and incorporation in subsequent releases.               */
  10464.  /*                                                                  */
  10465.  /********************************************************************/
  10466.  
  10467. #pragma  csect(code,  "NN@COPY ")
  10468. #pragma  csect(static,"NN$COPY ")
  10469. #include "nn.h"
  10470.  
  10471. /****** Copy string to non-volatile memory. **************************/
  10472.  
  10473. char *
  10474. NNMcopy(np,string)
  10475. Rstruc nncb *np;
  10476. char        *string;
  10477. {
  10478.  int         len = strlen(string);
  10479.  char       *cp;
  10480.  
  10481.  /* cheapo one malloc per string right now */
  10482.  
  10483.  GETMAIN(cp,char,len+1,"copy of string");
  10484.  if (!cp) return NULL;
  10485.  strcpy(cp,string);
  10486.  
  10487.  return cp;
  10488. }
  10489.  
  10490. ./   ADD NAME=NNMDCAN,SSI=01020000
  10491.  
  10492.  /********************************************************************/
  10493.  /*                                                                  */
  10494.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10495.  /*                                                                  */
  10496.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  10497.  /*                                                                  */
  10498.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10499.  /* including the implied warranties of merchantability and fitness, */
  10500.  /* are expressly denied.                                            */
  10501.  /*                                                                  */
  10502.  /* Provided this copyright notice is included, this software may    */
  10503.  /* be freely distributed and not offered for sale.                  */
  10504.  /*                                                                  */
  10505.  /* Changes or modifications may be made and used only by the maker  */
  10506.  /* of same, and not further distributed.  Such modifications should */
  10507.  /* be mailed to the author for consideration for addition to the    */
  10508.  /* software and incorporation in subsequent releases.               */
  10509.  /*                                                                  */
  10510.  /********************************************************************/
  10511.  
  10512. #pragma  csect(code,  "NN@DCAN ")
  10513. #pragma  csect(static,"NN$DCAN ")
  10514. #include "nn.h"
  10515.  
  10516. #define NEWSGROUPS_LENGTH   256-sizeof("Newsgroups: ")
  10517. #define SUBJECT_LENGTH      256-sizeof("Subject: ")
  10518. #define PATH_LENGTH         256-sizeof("Path: ")
  10519. #define FROM_LENGTH         256-sizeof("From: ")
  10520. #define APPROVED_LENGTH     256-sizeof("Approved: ")
  10521. #define CONTROL_LENGTH      256-sizeof("Control: ")
  10522. #define CANCEL_LENGTH       128-sizeof("cancel ")
  10523.  
  10524. /*
  10525.  * Note:  The algorithm for determining whether the user can cancel
  10526.  *        an article is:
  10527.  *
  10528.  *        (1) The article's FROM header must match the user's
  10529.  *            identification - i.e. userid@machine.host
  10530.  *
  10531.  *        - OR -
  10532.  *
  10533.  *        (2) if the article has an Approved: header, the user's
  10534.  *            identification must match the Approved: header.
  10535.  *            The assumption is that the Approved: header is the
  10536.  *            ID of the moderator of the newsgroup.
  10537.  *
  10538.  */
  10539.  
  10540. /****** Collect additional article headers that we may need. *********/
  10541.  
  10542. static void
  10543. get_more_headers(np,ap,from,approved)
  10544. Rstruc nncb          *np;
  10545. Rstruc newsarticle   *ap;
  10546. char                 *from;
  10547. char                 *approved;
  10548. {
  10549.  struct textline     *tp;
  10550.  struct texthdr      *thp;
  10551.  char                *cp;
  10552.  char                *newp;
  10553.  char                *colonp;
  10554.  int                  header_index;
  10555.  char                 the_header[INTERNET_SIZE];
  10556.  
  10557.  strcpy(from, "");
  10558.  strcpy(approved, "");
  10559.  
  10560.  if (!ap) return;
  10561.  
  10562.  /* Grovel through headers looking for what we want.
  10563.   */
  10564.  
  10565.  newp = NULL;
  10566.  thp = &ap->thdr;
  10567.  strcpy(the_header,"");
  10568.  for (tp=thp->first_text_line; tp; tp=tp->next) {
  10569.    if (tp->text[0] == '\0') break;
  10570.    if (tp->text[0] == ' '
  10571.     || tp->text[0] == '\t') {
  10572.      cp = skip_whitespace(tp->text);
  10573.      if (*cp == '\0') break;
  10574.    }
  10575.    else {
  10576.      header_index = 0;
  10577.      colonp = strchr(tp->text,':');
  10578.      if (!colonp) break;
  10579.      strcpy(the_header,"");
  10580.      for (cp = tp->text;cp<colonp;cp++) {
  10581.        the_header[header_index++] = toupper(*cp);
  10582.      }
  10583.      the_header[header_index] = '\0';
  10584.      cp = skip_whitespace(colonp+1);
  10585.    }
  10586.    if      (EQUAL(the_header,"FROM"))
  10587.            strncat(from,cp,FROM_LENGTH);
  10588.    else if (EQUAL(the_header,"APPROVED"))
  10589.            strncat(approved,cp,APPROVED_LENGTH);
  10590.  }
  10591.  
  10592.  lowercase_and_strip_trailing_in_place(from);
  10593.  lowercase_and_strip_trailing_in_place(approved);
  10594.  
  10595.  return; 
  10596.  
  10597. }
  10598.  
  10599. /****** Cancel a news article. ***************************************/
  10600.  
  10601. Bool
  10602. NNMdcan(np,gp,ap)
  10603. Rstruc nncb         *np;
  10604. Rstruc newsgroup    *gp;
  10605. Rstruc newsarticle  *ap;
  10606. {
  10607.  Bool                posted_ok     = FALSE;
  10608.  Bool                post_error    = FALSE;
  10609.  int                 prc;
  10610.  char               *lp;
  10611.  char               *cp;
  10612.  char               *article_check_field;
  10613.  struct tm          *nowtime;
  10614.  time_t              ltime;
  10615.  char                datestr[64];
  10616.  char                midstr [64];
  10617.  char                zuser   [9];
  10618.  char                temp   [12];
  10619.  char                post_message_id    [128];
  10620.  char                post_subject       [SUBJECT_LENGTH];
  10621.  char                post_path          [PATH_LENGTH];
  10622.  char                post_newsgroups    [NEWSGROUPS_LENGTH];
  10623.  char                post_from          [FROM_LENGTH];
  10624.  char                post_control       [CONTROL_LENGTH];
  10625.  char                post_grape_nuts    [CANCEL_LENGTH];
  10626.  char                article_from       [FROM_LENGTH];
  10627.  char                article_approved   [APPROVED_LENGTH];
  10628.  
  10629.  (void)NNMivget(np,"ZUSER ",zuser,sizeof(zuser));
  10630.  
  10631.  /* assert ap is not null */
  10632.  
  10633.  strcpy (post_newsgroups, gp->name);
  10634.  sprintf(post_path,       "%s!%s", np->client_hostname, zuser);
  10635.  sprintf(post_grape_nuts, "cancel %s", ap->message_id);
  10636.  strcpy (post_subject,    post_grape_nuts);
  10637.  strcpy (post_control,    post_grape_nuts);
  10638.  sprintf(post_from,       "%s@%s", zuser, np->client_hostname);
  10639.  
  10640.  lowercase_in_place(post_from);
  10641.  
  10642.  get_more_headers(np,ap,article_from,article_approved);
  10643.  if ((cp=strpbrk(article_from,     " \t"))) *cp = '\0';
  10644.  if ((cp=strpbrk(article_approved, " \t"))) *cp = '\0';
  10645.  
  10646.  if (*article_approved) article_check_field = article_approved;
  10647.  else                   article_check_field = article_from;
  10648.  
  10649.  if (UNEQUAL(article_check_field, post_from)) {
  10650.    ERR3("Cancel refused.  You, %s, are not %s.",
  10651.         post_from, article_check_field);
  10652.    return FALSE;
  10653.  }
  10654.  
  10655.  /* Display confirmation panel containing the following info:
  10656.   *
  10657.   * newsgroup name  = NNCGROUP
  10658.   * article number  = NNCNUM
  10659.   * article subject = NNCSUBJ
  10660.   * message ID      = NNCMSGID
  10661.   */
  10662.  
  10663.  if (!np->batch_mode) {
  10664.    sprintf(temp,"%d",ap->number);
  10665.    (void)NNMivput(np,"NNCGROUP ",gp->name,         -1);
  10666.    (void)NNMivput(np,"NNCNUM   ",temp,             -1);
  10667.    (void)NNMivput(np,"NNCSUBJ  ",ap->subject,      -1);
  10668.    (void)NNMivput(np,"NNCMSGID ",ap->message_id,   -1);
  10669.    (void)NNMispf(np,"ADDPOP");
  10670.    (void)NNMispf(np,"DISPLAY PANEL(NNMPCAN)");
  10671.    prc = np->ispfrc;
  10672.    (void)NNMispf(np,"REMPOP");
  10673.    if (prc > 0) { /* see if user pressed END */
  10674.      WARN1("Operation cancelled, because you pressed END.");
  10675.      return FALSE;
  10676.    }
  10677.  }
  10678.  
  10679.  /* Start posting here.
  10680.   *
  10681.   * Me:     POST
  10682.   * Server: 340 send article to be posted.  End with <CR-LF>.<CR-LF>
  10683.   *     or: 440 posting not allowed
  10684.   * If 430...
  10685.   *
  10686.   * See RFC850 for details.
  10687.   *
  10688.   * Me:     required_header: xxx
  10689.   * ...
  10690.   * Me:     <null line>
  10691.   * Me:     <text with leading periods hacked>
  10692.   * Me:     .
  10693.   * Server: 240 article posted OK
  10694.   *     or: 441 posting failed
  10695.   */
  10696.  
  10697.   /* See NNMDPOST for more information. */
  10698.  
  10699.  /* Get current date and time, and generate a message id from it.
  10700.   * If the message id is a duplicate, loop around until it isn't.
  10701.   */
  10702.  
  10703.  do {
  10704.  
  10705.    time(<ime);
  10706.    nowtime = localtime(<ime);
  10707.    strftime(datestr,sizeof(datestr)-1,"%a, %d %b %Y %H:%M %Z",nowtime);
  10708.    strftime(midstr, sizeof(midstr)-1, "%Y%m%d%H%M%S",nowtime);
  10709.  
  10710.    sprintf(post_message_id, "<%s%s@%s>",
  10711.                             midstr, zuser, np->client_hostname);
  10712.  
  10713.  } while (EQUAL(post_message_id,np->messageid));
  10714.  
  10715.  strcpy(np->messageid,post_message_id);
  10716.  
  10717.  posted_ok = FALSE;
  10718.  
  10719.  do {
  10720.    strcpy(np->nntp_command,"POST");
  10721.    if (!NNMsockt(np))     break;  /* Send socket command to server */
  10722.    if (!NNMgsrvl(np,&lp)) break;  /* Get server line */
  10723.    switch (np->nntp_message_num) {
  10724.      case 340: post_error = FALSE;
  10725.                break;
  10726.      case 440: ERR2(
  10727.        "Cancellation failed.  Server %s did not accept the post.",
  10728.                     np->nnserver);
  10729.                post_error = TRUE;
  10730.                break;
  10731.      default:  NNMrperr(np);       /* Report protocol error */
  10732.                post_error = TRUE;
  10733.                break;
  10734.    }
  10735.  
  10736.    if (post_error) break;
  10737.  
  10738.    /* Assert np->server_finished_replying == TRUE
  10739.     *     && np->receiving_text == TRUE
  10740.     */
  10741.  
  10742.    sprintf(np->nntp_command,"Path: %s", post_path);
  10743.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  10744.  
  10745.    sprintf(np->nntp_command,"Newsgroups: %s",post_newsgroups);
  10746.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  10747.  
  10748.    sprintf(np->nntp_command,"Subject: %s",post_subject);
  10749.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  10750.  
  10751.    sprintf(np->nntp_command,"Message-ID: %s", post_message_id);
  10752.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  10753.  
  10754.    sprintf(np->nntp_command,"From: %s", post_from);
  10755.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  10756.  
  10757.    sprintf(np->nntp_command,"Date: %s", datestr);
  10758.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  10759.  
  10760.    if (*article_approved) {
  10761.      sprintf(np->nntp_command,"Approved: %s", article_approved);
  10762.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  10763.    }
  10764.  
  10765.    sprintf(np->nntp_command,"Control: %s", post_control);
  10766.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  10767.  
  10768.    strcpy(np->nntp_command,"");
  10769.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  10770.  
  10771.    strcpy(np->nntp_command,post_grape_nuts);
  10772.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  10773.  
  10774.    strcpy(np->nntp_command,".");
  10775.    if (!NNMsockt(np)) break;   /* Send socket command to server */
  10776.  
  10777.    if (!NNMgsrvl(np,&lp)) break;  /* Get server line */
  10778.    switch (np->nntp_message_num) {
  10779.      case 240: posted_ok = TRUE;
  10780.                break;
  10781.      case 441: NNMclrtx(np,NULL);               /* Clear text */
  10782.                NNMouttx(np,np->server_buf,NULL);/* Output text line */
  10783.                NNMvtx(np,NULL,NULL);            /* View text */
  10784.  ERR2("Cancel failed.  Server %s rejected the post.",np->nnserver);
  10785.                posted_ok = FALSE;
  10786.                break;
  10787.      default:  NNMrperr(np);       /* Report protocol error */
  10788.                posted_ok = FALSE;
  10789.                break;
  10790.    }
  10791.  
  10792.    NNMesrvr(np);                   /* End server read */
  10793.  
  10794.    break;
  10795.  
  10796.  } while(FALSE); /* one-time DO so I can break out of it */
  10797.  
  10798.  if (!posted_ok) return FALSE;
  10799.  
  10800.  WARN4("Cancel request for %s article %d sent to server %s.",
  10801.        gp->name, ap->number, np->nnserver);
  10802.  
  10803.  return TRUE;
  10804. }
  10805.  
  10806. ./   ADD NAME=NNMDFAIL,SSI=01000029
  10807.  
  10808.  /********************************************************************/
  10809.  /*                                                                  */
  10810.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10811.  /*                                                                  */
  10812.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10813.  /* including the implied warranties of merchantability and fitness, */
  10814.  /* are expressly denied.                                            */
  10815.  /*                                                                  */
  10816.  /* Provided this copyright notice is included, this software may    */
  10817.  /* be freely distributed and not offered for sale.                  */
  10818.  /*                                                                  */
  10819.  /* Changes or modifications may be made and used only by the maker  */
  10820.  /* of same, and not further distributed.  Such modifications should */
  10821.  /* be mailed to the author for consideration for addition to the    */
  10822.  /* software and incorporation in subsequent releases.               */
  10823.  /*                                                                  */
  10824.  /********************************************************************/
  10825.  
  10826. #pragma  csect(code,  "NN@DFAIL")
  10827. #pragma  csect(static,"NN$DFAIL")
  10828. #include "nn.h"
  10829.  
  10830. /****** Retrieve allocation failure messages. ************************/
  10831.  
  10832. void
  10833. NNMdfail(rc,p99)
  10834. int            rc;
  10835. __S99parms    *p99;
  10836. {
  10837.  int           zero = 0;
  10838.  unsigned int  dfid = 0x40320000;
  10839.  struct {
  10840.          short first_level_msg_len;
  10841.          short first_level_msg_offset;
  10842.          char  first_level_msg[251];
  10843.          short second_level_msg_len;
  10844.          short second_level_msg_offset;
  10845.          char  second_level_msg[251];
  10846.         }      dfbuffer;
  10847.  
  10848.  static int (*ikjeff18_pointer)() = NULL;
  10849.  
  10850. #ifndef FETCH
  10851.  extern int *ikjeff18();
  10852. #endif
  10853.  
  10854.  if (!ikjeff18_pointer) {
  10855. #ifdef FETCH
  10856.    ikjeff18_pointer = (int (*)())fetch("IKJEFF18");
  10857. #else
  10858.    ikjeff18_pointer = (int (*)())ikjeff18;
  10859. #endif
  10860.  }
  10861.  
  10862.  dfbuffer.first_level_msg_len = 4;
  10863.  dfbuffer.second_level_msg_len = 4;
  10864.  
  10865.  if (ikjeff18_pointer) {
  10866.    if ((*ikjeff18_pointer)(p99,&rc,&zero,&dfid,&zero,&dfbuffer)) {
  10867.      fprintf(stderr,"IKJEFF18 returned a nonzero return code\n");
  10868.    }
  10869.    if (dfbuffer.first_level_msg_len > 0) {
  10870.      fprintf(stderr,"%*.*s\n",
  10871.                     dfbuffer.first_level_msg_len-4,
  10872.                     dfbuffer.first_level_msg_len-4,
  10873.                     dfbuffer.first_level_msg);
  10874.    }
  10875.    if (dfbuffer.second_level_msg_len > 0) {
  10876.      fprintf(stderr,"%*.*s\n",
  10877.                     dfbuffer.second_level_msg_len-4,
  10878.                     dfbuffer.second_level_msg_len-4,
  10879.                     dfbuffer.second_level_msg);
  10880.    }
  10881.  }
  10882.  else {
  10883. #ifdef FETCH
  10884.    fprintf(stderr,"NNMVS: Cannot fetch IKJEFF18\n");
  10885. #else
  10886.    fprintf(stderr,"Cannot call IKJEFF18, not linked with NNMVS\n");
  10887. #endif
  10888.  }
  10889.  return; 
  10890. }
  10891.  
  10892. ./   ADD NAME=NNMDISC,SSI=01000053
  10893.  
  10894.  /********************************************************************/
  10895.  /*                                                                  */
  10896.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  10897.  /*                                                                  */
  10898.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  10899.  /* including the implied warranties of merchantability and fitness, */
  10900.  /* are expressly denied.                                            */
  10901.  /*                                                                  */
  10902.  /* Provided this copyright notice is included, this software may    */
  10903.  /* be freely distributed and not offered for sale.                  */
  10904.  /*                                                                  */
  10905.  /* Changes or modifications may be made and used only by the maker  */
  10906.  /* of same, and not further distributed.  Such modifications should */
  10907.  /* be mailed to the author for consideration for addition to the    */
  10908.  /* software and incorporation in subsequent releases.               */
  10909.  /*                                                                  */
  10910.  /********************************************************************/
  10911.  
  10912. #pragma  csect(code,  "NN@DISC ")
  10913. #pragma  csect(static,"NN$DISC ")
  10914. #include "nn.h"
  10915.  
  10916. /****** Disconnect from news server. *********************************/
  10917.  
  10918. void
  10919. NNMdisc(np)
  10920. Rstruc nncb *np;
  10921. {
  10922.  int closerc;
  10923.  
  10924.  np->reconnect_in_progress = FALSE;
  10925.  np->closing_connection    = TRUE;
  10926.  
  10927.  if (np->connection_broken) {
  10928.    if (np->debug_file) {
  10929.      fprintf(np->debug_file,
  10930.     "Client %s (%s) connection with news server on %s (%s) was lost\n",
  10931.           np->client_hostname, np->client_ip_addrstr,
  10932.           np->server_hostname, np->server_ip_addrstr);
  10933.    }
  10934.    if (np->batch_mode) {
  10935.      fprintf(np->batch_outfile,
  10936.     "Client %s (%s) connection with news server on %s (%s) was lost\n",
  10937.           np->client_hostname, np->client_ip_addrstr,
  10938.           np->server_hostname, np->server_ip_addrstr);
  10939.    }
  10940.    np->connected_to_server   = FALSE;
  10941.  }
  10942.  else {
  10943.  
  10944.    np->newsgroup_selected    = FALSE;
  10945.    np->current_newsgroup     = NULL;
  10946.  
  10947.    /* In case of some kind of protocol error, don't let things hang. */
  10948.  
  10949.    NNMesrvr(np);         /* End server read */
  10950.  
  10951.    if (np->debug_file) {
  10952.      fprintf(np->debug_file,
  10953.           "Client %s (%s) disconnecting from news server on %s (%s)\n",
  10954.           np->client_hostname, np->client_ip_addrstr,
  10955.           np->server_hostname, np->server_ip_addrstr);
  10956.    }
  10957.  
  10958.    if (np->batch_mode) {
  10959.      fprintf(np->batch_outfile,
  10960.           "Client %s (%s) disconnecting from news server on %s (%s)\n",
  10961.           np->client_hostname, np->client_ip_addrstr,
  10962.           np->server_hostname, np->server_ip_addrstr);
  10963.    }
  10964.    else {
  10965.      (void)NNMivput(np,"NNSOLDER ",np->server_hostname,-1);
  10966.      (void)NNMivput(np,"NNSOLDIP ",np->server_ip_addrstr,-1);
  10967.      (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  10968.      (void)NNMispf(np,"DISPLAY PANEL(NNMLDISC)");
  10969.  
  10970.    }
  10971.  
  10972.    /* Send the server a QUIT request.  In the past we got away without
  10973.     * doing this.  However, this is important for one reason:
  10974.     * If the connection was lost before we attempt the disconnect,
  10975.     * we want to know about it so that we don't attempt the close.
  10976.     * The best way to find out is to try to send something.
  10977.     * Fortunately, the protocol fits right in with that need.
  10978.     */
  10979.  
  10980.    strcpy(np->nntp_command,"QUIT");
  10981.    if (!NNMsockt(np)) return;      /* Send socket command to server */
  10982.  
  10983.    /* In case of some kind of protocol error, don't let things hang. */
  10984.  
  10985.    NNMesrvr(np);                   /* End server read */
  10986.  
  10987.    np->connected_to_server   = FALSE;
  10988.  
  10989.    TCP_DEBUG_ON;
  10990.    closerc = close(np->socknum);
  10991.    TCP_DEBUG_OFF;
  10992.  
  10993.    if (closerc < 0) {
  10994.      ERR2("TCP/IP error: close() failed to disconnect from server %s.",
  10995.           np->nnserver);
  10996.    }
  10997.  }
  10998.  
  10999.  return; 
  11000. }
  11001.  
  11002. ./   ADD NAME=NNMDISPL,SSI=01000011
  11003.  
  11004.  /********************************************************************/
  11005.  /*                                                                  */
  11006.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11007.  /*                                                                  */
  11008.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  11009.  /*                                                                  */
  11010.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11011.  /* including the implied warranties of merchantability and fitness, */
  11012.  /* are expressly denied.                                            */
  11013.  /*                                                                  */
  11014.  /* Provided this copyright notice is included, this software may    */
  11015.  /* be freely distributed and not offered for sale.                  */
  11016.  /*                                                                  */
  11017.  /* Changes or modifications may be made and used only by the maker  */
  11018.  /* of same, and not further distributed.  Such modifications should */
  11019.  /* be mailed to the author for consideration for addition to the    */
  11020.  /* software and incorporation in subsequent releases.               */
  11021.  /*                                                                  */
  11022.  /********************************************************************/
  11023.  
  11024. #pragma  csect(code,  "NN@DISPL")
  11025. #pragma  csect(static,"NN$DISPL")
  11026. #include "nn.h"
  11027.  
  11028. #ifdef FETCH
  11029. #define VL_BIT(X) ((unsigned int)(X) | 0x80000000)
  11030. #else
  11031. #define VL_BIT(X) (X)
  11032. #endif
  11033.  
  11034. /****** Display ISPF panel. ******************************************/
  11035.  
  11036. int
  11037. NNMdispl(np,pan8)
  11038. Rstruc nncb    *np;
  11039. char           *pan8;
  11040. {
  11041.  
  11042.  if (np->setmsg) {
  11043.    np->ispfrc = ISPLINK("DISPLAY ", pan8, VL_BIT("ISRZ002 "));
  11044.  }
  11045.  else {
  11046.    np->ispfrc = ISPLINK("DISPLAY ", VL_BIT(pan8));
  11047.  }
  11048.  
  11049.  if (np->ispfrc > 8) NNMierr(np);   /* display ISPF error */
  11050.  
  11051.  np->setmsg = FALSE;
  11052.  
  11053.  return np->ispfrc;
  11054. }
  11055.  
  11056. ./   ADD NAME=NNMDLANG,SSI=01070041
  11057.  
  11058.  /********************************************************************/
  11059.  /*                                                                  */
  11060.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11061.  /*                                                                  */
  11062.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  11063.  /*                                                                  */
  11064.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11065.  /* including the implied warranties of merchantability and fitness, */
  11066.  /* are expressly denied.                                            */
  11067.  /*                                                                  */
  11068.  /* Provided this copyright notice is included, this software may    */
  11069.  /* be freely distributed and not offered for sale.                  */
  11070.  /*                                                                  */
  11071.  /* Changes or modifications may be made and used only by the maker  */
  11072.  /* of same, and not further distributed.  Such modifications should */
  11073.  /* be mailed to the author for consideration for addition to the    */
  11074.  /* software and incorporation in subsequent releases.               */
  11075.  /*                                                                  */
  11076.  /********************************************************************/
  11077.  
  11078. #pragma  csect(code,  "NN@DLANG")
  11079. #pragma  csect(static,"NN$DLANG")
  11080. #include "nn.h"
  11081.  
  11082. struct nndynarea {
  11083.                   struct newsgroup      *newsgroup;
  11084.                   char                   sel_attr;
  11085.                   char                   sel_field;
  11086.                   char                   name_attr;
  11087.                   char                   name[GROUP_NAME_SIZE];
  11088.                   char                   count_attr;
  11089.                   int                    count;
  11090.                  };
  11091.  
  11092. /****** Set date and time of last LIST or NEWGROUPS command. *********/
  11093.  
  11094. static void
  11095. set_date_and_time(np)
  11096. Rstruc nncb      *np;
  11097. {
  11098.   time_t          timeval;
  11099.   struct tm      *now;
  11100.  
  11101.   time(&timeval);
  11102.   now = localtime(&timeval);
  11103.   now->tm_mon++;             /* adjust for # of months since Jan. */
  11104.  
  11105.   sprintf(np->lastNGdate, "%02d%02d%02d",
  11106.                           now->tm_year, now->tm_mon, now->tm_mday);
  11107.   sprintf(np->lastNGtime, "%02d%02d%02d",
  11108.                           now->tm_hour, now->tm_min, now->tm_sec );
  11109.   return;
  11110. }
  11111.  
  11112. /****** Collect newsgroups using list from NEWSGROUPS request. *******/
  11113.  
  11114. static Bool
  11115. collect_newsgroups(np,just_new_groups)
  11116. Rstruc nncb         *np;
  11117. Fool                 just_new_groups;
  11118. {
  11119.  Rstruc newsgroup   *gp;
  11120.  struct newsgroup   *gpact;
  11121.  char               *lp;
  11122.  int                 list_first_article_number     = NO_VALUE;
  11123.  int                 list_last_article_number      = NO_VALUE;
  11124.  int                 ac;
  11125.  char                list_posting_allowed          = 'n';
  11126.  char                list_name[GROUP_NAME_SIZE]    = "";
  11127.  char                formatted_ac[12];
  11128.  
  11129.  np->sending_text = TRUE;
  11130.  gpact = NULL;
  11131.  
  11132.  for (;;) {
  11133.  
  11134.    if (!NNMgsrvl(np,&lp))    return FALSE;   /* Get server line */
  11135.    if (lp == NULL)           break;
  11136.    if (strcmp(lp,".") == 0)  break;
  11137.  
  11138.    if (just_new_groups) {
  11139.  
  11140.      /* Extract fields from response to "NEWGROUPS" socket request.
  11141.         Note that only newsgroup names are returned. */
  11142.  
  11143.      if (1 != sscanf(np->nntp_message_text, "%s", list_name)) {
  11144.        NNMrbfm(np);   /* Report bad format message */
  11145.        return FALSE;
  11146.      }
  11147.    }
  11148.    else {
  11149.  
  11150.      /* Extract fields from response to "LIST" socket request.
  11151.         Note that no article count is provided. */
  11152.  
  11153.      if (4 != sscanf(np->nntp_message_text, "%s %d %d %c",
  11154.                                  list_name,
  11155.                                 &list_last_article_number,
  11156.                                 &list_first_article_number,
  11157.                                 &list_posting_allowed       )) {
  11158.        NNMrbfm(np);   /* Report bad format message */
  11159.        return FALSE;
  11160.      }
  11161.    }
  11162.  
  11163.    if (just_new_groups) {
  11164.      ac = NO_VALUE;
  11165.      strcpy(formatted_ac,"");
  11166.    }
  11167.    else {
  11168.      ac = list_last_article_number - list_first_article_number + 1;
  11169.      sprintf(formatted_ac,"%d",ac);
  11170.    }
  11171.    if (!np->batch_mode) {
  11172.      if (np->update_adding_newsgroups) {
  11173.        (void)NNMivput(np,"NNLCOUNT ",formatted_ac,-1);
  11174.        (void)NNMivput(np,"NNLGROUP ",list_name,   -1);
  11175.        (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  11176.        (void)NNMispf(np,"DISPLAY PANEL(NNMLADDG)");
  11177.      }
  11178.    }
  11179.  
  11180.    gp = NNMaddng(np,list_name);           /* Add newsgroup */
  11181.  
  11182.    if (just_new_groups) {
  11183.      np->new_newsgroup_count++;
  11184.      ClearGroupStatus(gp);
  11185.      SetNewGroup(gp);
  11186.      gp->registered = -1;
  11187.      continue;
  11188.    }
  11189.  
  11190.    /* Put group in the proper "active file" order */
  11191.  
  11192.    if (gpact) gpact->next2 = gp;
  11193.    else       np->first_newsgroup_alt = gp;
  11194.    gp->next2 = NULL;
  11195.    gpact = gp;
  11196.  
  11197.    OffNoSuchGroup(gp);    /* came from LIST, must exist now */
  11198.  
  11199.    if (NullGroupStatus(gp)) {
  11200.      if (np->brand_new_newsrc) {
  11201.        gp->registered = 0;     /* new news user, no autosubscribes */
  11202.      }
  11203.      else {
  11204.        np->new_newsgroup_count++;
  11205.        SetNewGroup(gp);
  11206.        gp->registered = -1;
  11207.      }
  11208.    }
  11209.  
  11210.    /*
  11211.     * Logic:
  11212.     * This code sets up newsgroups from NNTP LIST.
  11213.     * They are already found in .newsrc (unless new newsgroups),
  11214.     * and probably aren't GROUPed yet, but may have been.
  11215.     * So there is a possibility of an article vector existing,
  11216.     * but in most cases there won't be.
  11217.     * The overriding principle here is that the active file knows
  11218.     * best what's up to date, and is the arbiter of the
  11219.     * low_number and high_number fields.  On the off chance
  11220.     * that NEWSRC implied different values for these, the
  11221.     * various adjustments in other routines should handle it.
  11222.     */
  11223.  
  11224.    if (GroupFromNewsrc(gp)
  11225.     || GroupFromNNTP(gp)) {          /* Adjust unread articles */
  11226.      NNMadjua(np,gp,ac,list_first_article_number,
  11227.                        list_last_article_number);
  11228.    }
  11229.    else {
  11230.      gp->unread_count = ac;
  11231.    }
  11232.  
  11233.    gp->low_number    = list_first_article_number;
  11234.    gp->high_number   = list_last_article_number;
  11235.    gp->article_count = ac;
  11236.  
  11237.    SetGroupListed(gp);
  11238.  
  11239.  }
  11240.  
  11241.  np->dont_reconnect = FALSE;
  11242.  
  11243.  return TRUE;
  11244.  
  11245. }
  11246.  
  11247. /****** Display new newsgroups. **************************************/
  11248.  
  11249. static Bool
  11250. display_new_newsgroups(np,just_new_groups)
  11251. Rstruc nncb           *np;
  11252. Fool                   just_new_groups;
  11253. {
  11254.  Rstruc newsgroup     *gp;
  11255.  Rstruc nndynarea     *dp;
  11256.  struct nndynarea     *nndynarea_address;
  11257.  int                   nndynarea_length;
  11258.  int                   i;
  11259.  int                   prc;
  11260.  int                   nnlvl;
  11261.  int                   depth;
  11262.  int                   depthx80;
  11263.  int                   zscrolln;
  11264.  int                   topoff;
  11265.  int                   dynsize;
  11266.  char                 *cp;
  11267.  char                 *nndyna;
  11268.  char                 *nndyna_slice;
  11269.  Bool                  retval;
  11270.  Bool                  is_max;
  11271.  char                  savechar;
  11272.  char                  zverb    [9];
  11273.  char                  zscrolla [9];
  11274.  char                  zcmd    [81];
  11275.  
  11276.  retval = TRUE;
  11277.  
  11278.  if (np->new_newsgroup_count == 0) return TRUE;
  11279.  
  11280.  /* Allocate a block of "nndynarea" new-newsgroup structures. */
  11281.  
  11282.  GETMAIN(nndynarea_address, struct nndynarea,
  11283.          np->new_newsgroup_count,"nndynarea");
  11284.  
  11285.  if (!nndynarea_address) return FALSE;
  11286.  
  11287.  nndynarea_length = np->new_newsgroup_count * sizeof(struct nndynarea);
  11288.  
  11289.  dp = nndynarea_address;
  11290.  for (i = 0, gp = np->first_newsgroup; gp; gp = gp->next) {
  11291.    if (NewGroup(gp)) {  /* if new newsgroup */
  11292.      dp->newsgroup = gp;
  11293.      strcpy(dp->name,gp->name);
  11294.      dp->count = gp->article_count;
  11295.      dp++;
  11296.      i++;
  11297.    }
  11298.  }
  11299.  
  11300.  if (i != np->new_newsgroup_count) {
  11301.    fprintf(stderr,
  11302.            "Possible news server bug: %d new groups but %d NEWGROUPS\n",
  11303.            i, np->new_newsgroup_count);
  11304.  }
  11305.  
  11306.  /* Preinitialize all newsgroups to unsubscribed. */
  11307.  
  11308.  for (dp = nndynarea_address; i > 0; dp++, i--) {
  11309.    gp = dp->newsgroup;
  11310.    gp->registered = 0;
  11311.    OffNewGroup(gp);
  11312.    dp->sel_attr   = DATAIN_HIGH;
  11313.    dp->sel_field  = ' ';
  11314.    dp->name_attr  = DATAOUT_LOW; /* since all unregistered init'ly */
  11315.    dp->count_attr = DATAOUT_LOW;
  11316.  }
  11317.  
  11318.  /* Display new newsgroups in dynamic area panel. */
  11319.  
  11320.  (void)NNMispf(np,
  11321.        "PQUERY PANEL(NNMDNEWG) AREANAME(NNDYNA) DEPTH(NNDEPTH)");
  11322.  if (np->ispfrc != 0) return FALSE;
  11323.  depth = NNMiget(np,"NNDEPTH ");
  11324.  depthx80 = depth * 80;
  11325.  topoff  = 0;
  11326.  dynsize = 80*(np->new_newsgroup_count + depth) + 1;
  11327.  
  11328.  GETMAIN(nndyna, char, dynsize+1, "NNDYNA buffer");
  11329.  if (!nndyna) return FALSE;
  11330.  memset(nndyna,' ',dynsize);
  11331.  
  11332.  for (i = 0, cp=nndyna; i < np->new_newsgroup_count; i++, cp+=80) {
  11333.    dp = &nndynarea_address[i];
  11334.    memset(cp,' ',80);
  11335.    cp[ 0] = dp->sel_attr;
  11336.    cp[ 1] = dp->sel_field;
  11337.    cp[ 2] = dp->name_attr;
  11338.    memcpy(&cp[3],dp->name,strlen(dp->name));
  11339.    if (!just_new_groups) {
  11340.      cp[62] = dp->count_attr;
  11341.      sprintf(&cp[63],"%7d article%c",dp->count,
  11342.                                      dp->count == 1 ? ' ' : 's');
  11343.      cp[79] = ' ';
  11344.    }
  11345.  }
  11346.  
  11347.  (void)NNMivput(np,"NNDN1ST ","YES",-1);
  11348.  
  11349.  do {
  11350.    (void)NNMivput(np,"ZCMD ","",-1);
  11351.    (void)NNMivput(np,"NNDYNA ",nndyna+topoff*80,depthx80);
  11352.    prc = NNMdispl(np,"NNMDNEWG");
  11353.    if (prc > 8) break;
  11354.    (void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
  11355.    if (zcmd[0] == 'Q'    /* QUIT   */
  11356.     || zcmd[0] == 'C') { /* CANCEL */
  11357.      retval = FALSE;
  11358.      break;
  11359.    }
  11360.    nnlvl = NNMiget(np,"NNLVL ");
  11361.    nndyna_slice = nndyna + topoff*80;
  11362.    savechar = nndyna_slice[depthx80];
  11363.    (void)NNMivget(np,"NNDYNA ",nndyna_slice,depthx80);
  11364.    nndyna_slice[depthx80] = savechar;
  11365.    for (i = 0, cp=nndyna_slice; i < nnlvl; i++, cp+=80) {
  11366.      if (i+topoff >= np->new_newsgroup_count) break;
  11367.      dp = &nndynarea_address[i+topoff];
  11368.      gp = dp->newsgroup;
  11369.      dp->sel_field = ' ';
  11370.      switch (cp[1]) {
  11371.        case 'r':
  11372.        case 'R': gp->registered = 1;
  11373.                  cp[1] = ' ';
  11374.                  cp[2] = DATAOUT_HIGH;
  11375.                  break;
  11376.        case 'd':
  11377.        case 'D': gp->registered = 0;
  11378.                  cp[1] = ' ';
  11379.                  cp[2] = DATAOUT_LOW;
  11380.                  break;
  11381.        case 'q':
  11382.        case 'Q': NNMqng(np,gp);
  11383.                  cp[1] = ' ';
  11384.                  break;
  11385.        case ' ': break;
  11386.        default:
  11387.                  cp[1] = '?';
  11388.                  cp[2] = DATAOUT_LOW;
  11389.                  break;
  11390.      }
  11391.    }
  11392.    (void)NNMivget(np,"ZVERB ",zverb,sizeof(zverb));
  11393.    (void)NNMivget(np,"ZSCROLLA ",zscrolla,sizeof(zscrolla));
  11394.    zscrolln = NNMiget(np,"ZSCROLLN ");
  11395.    is_max = EQUAL(zscrolla,"MAX");
  11396.    if      (EQUAL(zverb,"DOWN")) {
  11397.      if (is_max) topoff = np->new_newsgroup_count - nnlvl;
  11398.      else        topoff += zscrolln;
  11399.    }
  11400.    else if (EQUAL(zverb,"UP")) {
  11401.      if (is_max) topoff = 0;
  11402.      else        topoff -= zscrolln;
  11403.    }
  11404.    if (topoff < 0)
  11405.        topoff = 0;
  11406.    if (topoff > np->new_newsgroup_count)
  11407.        topoff = np->new_newsgroup_count;
  11408.  
  11409.  } while (prc == 0);
  11410.  
  11411.  FREEMAIN(nndyna,"NNDYNA buffer");
  11412.  FREEMAIN(nndynarea_address,"nndynarea");
  11413.  
  11414.  return retval;
  11415. }
  11416.  
  11417. /****** Display bogus newsgroups. ************************************/
  11418.  
  11419. static Bool
  11420. display_bogus_newsgroups(np)
  11421. Rstruc nncb           *np;
  11422. {
  11423.  Rstruc newsgroup     *gp;
  11424.  Rstruc nndynarea     *dp;
  11425.  struct nndynarea     *nndynarea_address;
  11426.  int                   nndynarea_length;
  11427.  int                   i;
  11428.  int                   prc;
  11429.  int                   nnlvl;
  11430.  int                   depth;
  11431.  int                   depthx80;
  11432.  int                   zscrolln;
  11433.  int                   topoff;
  11434.  int                   dynsize;
  11435.  int                   bogus_newsgroup_count;
  11436.  char                 *cp;
  11437.  char                 *k;
  11438.  char                 *nndyna;
  11439.  char                 *nndyna_slice;
  11440.  Bool                  retval;
  11441.  Bool                  is_max;
  11442.  char                  savechar;
  11443.  char                  zverb    [9];
  11444.  char                  zscrolla [9];
  11445.  char                  zcmd    [81];
  11446.  
  11447.  retval = TRUE;
  11448.  
  11449.  bogus_newsgroup_count = 0;
  11450.  
  11451.  for (gp = np->first_newsgroup; gp; gp = gp->next) {
  11452.    if (BogusGroup(gp)) bogus_newsgroup_count++;
  11453.  }
  11454.  
  11455.  if (bogus_newsgroup_count == 0) return TRUE;
  11456.  
  11457.  /* Allocate a block of "nndynarea" new-newsgroup structures. */
  11458.  
  11459.  GETMAIN(nndynarea_address, struct nndynarea,
  11460.          bogus_newsgroup_count,"nndynarea");
  11461.  
  11462.  if (!nndynarea_address) return FALSE;
  11463.  
  11464.  nndynarea_length = bogus_newsgroup_count * sizeof(struct nndynarea);
  11465.  
  11466.  dp = nndynarea_address;
  11467.  for (i = 0, gp = np->first_newsgroup; gp; gp = gp->next) {
  11468.    if (BogusGroup(gp)) {
  11469.      SetNoSuchGroup(gp);
  11470.      OffGroupFromNewsrc(gp);
  11471.      dp->newsgroup = gp;
  11472.      strcpy(dp->name,gp->name);
  11473.      dp++;
  11474.    }
  11475.  }
  11476.  
  11477.  for(dp = nndynarea_address, i=bogus_newsgroup_count; i>0; dp++, i--) {
  11478.    dp->sel_attr   = DATAIN_HIGH;
  11479.    dp->sel_field  = ' ';
  11480.    dp->name_attr  = DATAOUT_LOW; /* since all unregistered init'ly */
  11481.  }
  11482.  
  11483.  /* Display bogus newsgroups in dynamic area panel. */
  11484.  
  11485.  (void)NNMispf(np,
  11486.        "PQUERY PANEL(NNMDBOGG) AREANAME(NNDYNA) DEPTH(NNDEPTH)");
  11487.  if (np->ispfrc != 0) return FALSE;
  11488.  depth = NNMiget(np,"NNDEPTH ");
  11489.  depthx80 = depth * 80;
  11490.  topoff  = 0;
  11491.  dynsize = 80*(bogus_newsgroup_count + depth) + 1;
  11492.  
  11493.  GETMAIN(nndyna, char, dynsize+1, "NNDYNA buffer");
  11494.  if (!nndyna) return FALSE;
  11495.  memset(nndyna,' ',dynsize);
  11496.  
  11497.  for (i = 0, cp=nndyna; i < bogus_newsgroup_count; i++, cp+=80) {
  11498.    dp = &nndynarea_address[i];
  11499.    memset(cp,' ',80);
  11500.    cp[ 0] = dp->sel_attr;
  11501.    cp[ 1] = dp->sel_field;
  11502.    cp[ 2] = dp->name_attr;
  11503.    strncpy(&cp[3],dp->name,67);
  11504.    if ((k=memchr(&cp[3],'\0',67))) *k = ' ';
  11505.    cp[70] = DATAOUT_LOW;
  11506.    memcpy(&cp[71],"         ",9);
  11507.  }
  11508.  
  11509.  (void)NNMivput(np,"NNDB1ST ","YES",-1);
  11510.  
  11511.  do {
  11512.    (void)NNMivput(np,"ZCMD ","",-1);
  11513.    (void)NNMivput(np,"NNDYNA ",nndyna+topoff*80,depthx80);
  11514.    prc = NNMdispl(np,"NNMDBOGG");
  11515.    if (prc > 8) break;
  11516.    (void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
  11517.    if (zcmd[0] == 'Q'    /* QUIT   */
  11518.     || zcmd[0] == 'C') { /* CANCEL */
  11519.      retval = FALSE;
  11520.      break;
  11521.    }
  11522.    nnlvl = NNMiget(np,"NNLVL ");
  11523.    nndyna_slice = nndyna + topoff*80;
  11524.    savechar = nndyna_slice[depthx80];
  11525.    (void)NNMivget(np,"NNDYNA ",nndyna_slice,depthx80);
  11526.    nndyna_slice[depthx80] = savechar;
  11527.    for (i = 0, cp=nndyna_slice; i < nnlvl; i++, cp+=80) {
  11528.      if (i+topoff >= bogus_newsgroup_count) break;
  11529.      dp = &nndynarea_address[i+topoff];
  11530.      gp = dp->newsgroup;
  11531.      dp->sel_field = ' ';
  11532.      switch (cp[1]) {
  11533.        case 'd':
  11534.        case 'D': SetNoSuchGroup(gp);
  11535.                  OffGroupFromNewsrc(gp);
  11536.                  gp->low_number            = 0;
  11537.                  gp->high_number           = 0;
  11538.                  gp->unread_count          = 0;
  11539.                  gp->article_count         = 0;
  11540.                  gp->registered            = 0;
  11541.                  cp[ 1] = ' ';
  11542.                  cp[ 2] = DATAOUT_LOW;
  11543.                  cp[70] = DATAOUT_HIGH;
  11544.                  memcpy(&cp[71],"Deleted  ",9);
  11545.                  break;
  11546.        case 'k':
  11547.        case 'K': OffNoSuchGroup(gp);
  11548.                  SetGroupFromNewsrc(gp);
  11549.                  gp->low_number            = 0;
  11550.                  gp->high_number           = 0;
  11551.                  gp->unread_count          = 0;
  11552.                  gp->article_count         = 0;
  11553.                  cp[1] = ' ';
  11554.                  cp[70] = DATAOUT_HIGH;
  11555.                  memcpy(&cp[71],"Kept     ",9);
  11556.                  break;
  11557.        case 'q':
  11558.        case 'Q': NNMqng(np,gp);
  11559.                  cp[1] = ' ';
  11560.                  break;
  11561.        case ' ':
  11562.                  cp[1] = ' ';
  11563.                  cp[70] = DATAOUT_LOW;
  11564.                  break;
  11565.        default:
  11566.                  cp[1] = '?';
  11567.                  cp[70] = DATAOUT_HIGH;
  11568.                  memcpy(&cp[71],"What?    ",9);
  11569.                  break;
  11570.      }
  11571.    }
  11572.    (void)NNMivget(np,"ZVERB ",zverb,sizeof(zverb));
  11573.    (void)NNMivget(np,"ZSCROLLA ",zscrolla,sizeof(zscrolla));
  11574.    zscrolln = NNMiget(np,"ZSCROLLN ");
  11575.    is_max = EQUAL(zscrolla,"MAX");
  11576.    if      (EQUAL(zverb,"DOWN")) {
  11577.      if (is_max) topoff = bogus_newsgroup_count - nnlvl;
  11578.      else        topoff += zscrolln;
  11579.    }
  11580.    else if (EQUAL(zverb,"UP")) {
  11581.      if (is_max) topoff = 0;
  11582.      else        topoff -= zscrolln;
  11583.    }
  11584.    if (topoff < 0)
  11585.        topoff = 0;
  11586.    if (topoff > bogus_newsgroup_count)
  11587.        topoff = bogus_newsgroup_count;
  11588.  
  11589.  } while (prc == 0);
  11590.  
  11591.  FREEMAIN(nndyna,"NNDYNA buffer");
  11592.  FREEMAIN(nndynarea_address,"nndynarea");
  11593.  
  11594.  return retval;
  11595. }
  11596.  
  11597. /****** Option.....list all new newsgroups. **************************/
  11598.  
  11599. static Bool
  11600. list_new(np)
  11601. Rstruc nncb *np;
  11602. {
  11603.  char       *lp;
  11604.  char        mmddyy[9];
  11605.  char        hhmmss[9];
  11606.  
  11607.  lp = np->lastNGdate + strspn(np->lastNGdate,"0");
  11608.  if (*lp == '\0') {
  11609.    ERR1( 
  11610. "There is no previous date in the NEWSRC file.  Select the List option."
  11611.        );
  11612.    return FALSE;
  11613.  }
  11614.  
  11615.  sprintf(np->nntp_command, "NEWGROUPS %.6s %.6s",
  11616.                            np->lastNGdate, np->lastNGtime);
  11617.  
  11618.  if (!NNMsockt(np)) return FALSE;   /* Send socket command to server */
  11619.  
  11620.  sprintf(mmddyy,"%2.2s/%2.2s/%2.2s",
  11621.          &np->lastNGdate[2], &np->lastNGdate[4], &np->lastNGdate[0]);
  11622.  sprintf(hhmmss,"%2.2s:%2.2s:%2.2s",
  11623.          &np->lastNGtime[0], &np->lastNGtime[2], &np->lastNGtime[4]);
  11624.  
  11625.  if (np->update_adding_newsgroups) {
  11626.    if (!np->batch_mode) {
  11627.      (void)NNMivput(np,"NNNGDT ",mmddyy,-1);
  11628.      (void)NNMivput(np,"NNNGTM ",hhmmss,-1);
  11629.      (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  11630.      (void)NNMispf(np,"DISPLAY PANEL(NNMLNEWG)");
  11631.    }
  11632.  }
  11633.  
  11634.  if (!NNMgsrvl(np,&lp))             return FALSE; /* Get server line */
  11635.  if (np->nntp_message_num != 231)   NNMrperr(np);
  11636.  
  11637.  if (!collect_newsgroups(np,TRUE)) return FALSE;
  11638.  
  11639.  if (np->batch_mode) return TRUE;
  11640.  
  11641.  if (!display_new_newsgroups(np,TRUE)) return FALSE;
  11642.  
  11643.  set_date_and_time(np);
  11644.  
  11645.  if (np->new_newsgroup_count == 0) {
  11646.    ERR3( 
  11647. "No new newsgroups since last use of L or N option, on %s %s",
  11648.         mmddyy, hhmmss);
  11649.    return FALSE;
  11650.  }
  11651.  
  11652.  return TRUE;
  11653. }
  11654.  
  11655. /****** Option.....list all known newsgroups. ************************/
  11656.  
  11657. static Bool
  11658. list_all(np)
  11659. Rstruc nncb *np;
  11660. {
  11661.  char       *lp;
  11662.  
  11663.  strcpy(np->nntp_command,"LIST");
  11664.  if (!NNMsockt(np)) return FALSE;   /* Send socket command to server */
  11665.  
  11666.  if (!np->batch_mode) {
  11667.    (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  11668.    (void)NNMispf(np,"DISPLAY PANEL(NNMLLIST)");
  11669.  }
  11670.  
  11671.  if (!NNMgsrvl(np,&lp))             return FALSE; /* Get server line */
  11672.  if (np->nntp_message_num != 215)   NNMrperr(np);
  11673.  
  11674.  if (!collect_newsgroups(np,FALSE)) return FALSE;
  11675.  
  11676.  if (np->batch_mode) return TRUE;
  11677.  
  11678.  if (!display_new_newsgroups(np,FALSE)) return FALSE;
  11679.  
  11680.  if (!display_bogus_newsgroups(np)) return FALSE;
  11681.  
  11682.  set_date_and_time(np);
  11683.  
  11684.  np->new_newsgroup_count = 0;
  11685.  
  11686.  np->show_all_newsgroups = TRUE;
  11687.  
  11688.  return NNMvng(np);                           /* View newsgroups */
  11689. }
  11690.  
  11691. /****** Fake disconnect. ********************************************/
  11692.  
  11693. static void
  11694. fake_disconnect(np)
  11695. Rstruc nncb         *np;
  11696. {
  11697.  char               *dummy = "503 Simulated disconnect.";
  11698.  int                 index;
  11699.  
  11700.  /* fake a disconnect condition by sending an NNTP "QUIT".
  11701.   * The next attempt to communicate with the socket will get
  11702.   * the simulated response instead of what it expected.
  11703.   */
  11704.  
  11705.  strcpy(np->nntp_command,"QUIT");
  11706.  if (!NNMsockt(np)) return;        /* Send socket command to server */
  11707.  
  11708.  index = strlen(dummy);
  11709.  strcpy(np->g_buf+1,dummy);
  11710.  np->g_buf[index+1] = CARRIAGE_RETURN;
  11711.  np->g_buf[index+2] = LINE_FEED;
  11712.  np->g_bytes_returned = index+3;
  11713.  np->g_buf_index = 0;
  11714.  
  11715.  return; 
  11716. }
  11717.  
  11718. /****** List all or new groups. **************************************/
  11719.  
  11720. Bool
  11721. NNMdlang(np,option)
  11722. Rstruc nncb      *np;
  11723. enum list_option  option;
  11724. {
  11725.  
  11726.  /* Since an attempt to reconnect while reading data from the server
  11727.   * will leave the news reader in an inconsistent state and possibly
  11728.   * lead to destroyed newsrc file, we suppress all attempts to do an
  11729.   * automatic reconnection while this is in progress.
  11730.   */
  11731.  
  11732.  np->dont_reconnect = TRUE;
  11733.  
  11734.  switch (option) {
  11735.    case LIST_ALL:  return list_all(np);
  11736.    case LIST_NEW:  return list_new(np);
  11737.    case LIST_ALL_DISCONNECT:
  11738.                    fake_disconnect(np);
  11739.                    return list_all(np);
  11740.  }
  11741.  
  11742.  np->dont_reconnect = FALSE;
  11743.  
  11744. }
  11745.  
  11746. ./   ADD NAME=NNMDMAIL,SSI=01020048
  11747.  
  11748.  /********************************************************************/
  11749.  /*                                                                  */
  11750.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  11751.  /*                                                                  */
  11752.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  11753.  /*                                                                  */
  11754.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  11755.  /* including the implied warranties of merchantability and fitness, */
  11756.  /* are expressly denied.                                            */
  11757.  /*                                                                  */
  11758.  /* Provided this copyright notice is included, this software may    */
  11759.  /* be freely distributed and not offered for sale.                  */
  11760.  /*                                                                  */
  11761.  /* Changes or modifications may be made and used only by the maker  */
  11762.  /* of same, and not further distributed.  Such modifications should */
  11763.  /* be mailed to the author for consideration for addition to the    */
  11764.  /* software and incorporation in subsequent releases.               */
  11765.  /*                                                                  */
  11766.  /********************************************************************/
  11767.  
  11768. #pragma  csect(code,  "NN@DMAIL")
  11769. #pragma  csect(static,"NN$DMAIL")
  11770. #include "nn.h"
  11771.  
  11772. #define TO_LENGTH          256-sizeof("To: ")
  11773. #define SUBJECT_LENGTH     256-sizeof("Subject: ")
  11774. #define FROM_LENGTH        256-sizeof("From: ")
  11775. #define REPLY_TO_LENGTH    256-sizeof("Reply-to: ")
  11776.  
  11777. /****** Determine to whom to reply, according to RFC822 standards ****/
  11778.  
  11779. static char *
  11780. to_whom_to_reply(np,ap)
  11781. Rstruc nncb          *np;
  11782. Rstruc newsarticle   *ap;
  11783. {
  11784.  struct textline     *tp;
  11785.  struct texthdr      *thp;
  11786.  char                *cp;
  11787.  char                *colonp;
  11788.  char                *resent_reply_to    = NULL;
  11789.  char                *resent_from        = NULL;
  11790.  char                *reply_to           = NULL;
  11791.  char                *from               = NULL;
  11792.  char                *resent_sender      = NULL;
  11793.  char                *sender             = NULL;
  11794.  int                  header_index;
  11795.  char                 the_header[INTERNET_SIZE];
  11796.  
  11797.  if (!ap) return "";
  11798.  
  11799.  /* Since RFC1036 (Standard for Interchange of USENET Messages)
  11800.   * seems to imply that RFC822 header format is OK, we would
  11801.   * expect to do this.  In reality, headers like Reply-to: are
  11802.   * often filled with the name of the mailing list (e.g. BITNET).
  11803.   * Therefore, the user needs to have the option of using
  11804.   * the From: header for replies.  Anyhow...
  11805.   */
  11806.  
  11807.  /* Grovel through headers looking for likely candidates.  The official
  11808.   * pecking order is:
  11809.   *
  11810.   * Resent-Reply-To:
  11811.   * Resent-From:
  11812.   * Reply-To:
  11813.   * From:
  11814.   * Resent-Sender:
  11815.   * Sender:
  11816.   *
  11817.   * If none of the above, punt by returning a null string.
  11818.   *
  11819.   * NOTE: There is no provision in this code for continued headers.
  11820.   *       If you want to handle continued headers, use the code in
  11821.   *       NNMDPOST as a model.  You will have to allocate your own
  11822.   *       storage to hold 'em.
  11823.   */
  11824.  
  11825.  thp = &ap->thdr;
  11826.  strcpy(the_header,"");
  11827.  for (tp=thp->first_text_line; tp; tp=tp->next) {
  11828.    if (tp->text[0] == '\0') break;
  11829.    if (tp->text[0] == ' '
  11830.     || tp->text[0] == '\t') {
  11831.      cp = skip_whitespace(tp->text);
  11832.      if (*cp == '\0') break;
  11833.    }
  11834.    else {
  11835.      header_index = 0;
  11836.      colonp = strchr(tp->text,':');
  11837.      if (!colonp) break;
  11838.      strcpy(the_header,"");
  11839.      for (cp = tp->text;cp<colonp;cp++) {
  11840.        the_header[header_index++] = toupper(*cp);
  11841.      }
  11842.      the_header[header_index] = '\0';
  11843.    }
  11844.    cp = skip_whitespace(colonp+1);
  11845.  
  11846.    if      (!strcmp(the_header,"RESENT-REPLY-TO")) resent_reply_to = cp;
  11847.    else if (!strcmp(the_header,"RESENT-FROM"    )) resent_from     = cp;
  11848.    else if (!strcmp(the_header,"REPLY-TO"       )) reply_to        = cp;
  11849.    else if (!strcmp(the_header,"FROM"           )) from            = cp;
  11850.    else if (!strcmp(the_header,"RESENT-SENDER"  )) resent_sender   = cp;
  11851.    else if (!strcmp(the_header,"SENDER"         )) sender          = cp;
  11852.  }
  11853.  
  11854.  return (resent_reply_to ? resent_reply_to :
  11855.          resent_from     ? resent_from     :
  11856.          reply_to        ? reply_to        :
  11857.          from            ? from            :
  11858.          resent_sender   ? resent_sender   :
  11859.          sender          ? sender          :
  11860.          "");
  11861.  
  11862. }
  11863.  
  11864. /****** Reply to a news article by mail, or just mail a message ******/
  11865.  
  11866. void
  11867. NNMdmail(np,gp,ap)
  11868. Rstruc nncb         *np;
  11869. Rstruc newsgroup    *gp;
  11870. Rstruc newsarticle  *ap;
  11871. {
  11872.  Bool                filled       = FALSE;
  11873.  Bool                edit_error   = FALSE;
  11874.  Bool                mail_error   = FALSE;
  11875.  int                 l;
  11876.  int                 display_rc;
  11877.  FILE               *efp          = NULL;
  11878.  FILE               *mfp          = NULL;
  11879.  FILE               *sfp          = NULL;
  11880.  struct tm          *now;
  11881.  char               *cp;
  11882.  time_t              ltime;
  11883.  char                datestr [64];
  11884.  char                midstr  [64];
  11885.  char                zuser   [ 9];
  11886.  char                tempdsn [L_tmpnam];
  11887.  char                outpdsn [L_tmpnam];
  11888.  char                editstr [40+L_tmpnam];
  11889.  char                edit_profile     [  9];
  11890.  char                signature_file   [ 64];
  11891.  char                mail_message_id  [128];
  11892.  char                zcmd             [ 81];
  11893.  char                nnmailfr         [FROM_LENGTH];
  11894.  char                nnmailrt         [REPLY_TO_LENGTH];
  11895.  char                mail_from        [FROM_LENGTH];
  11896.  char                mail_to          [TO_LENGTH];
  11897.  char                mail_subject     [SUBJECT_LENGTH];
  11898.  char                mailline         [260];
  11899.  char                sigline          [260];
  11900.  char                mail_command     [260];
  11901.  
  11902.  (void)NNMivget(np,"ZUSER ",zuser,sizeof(zuser));
  11903.  
  11904.  if (ap) {
  11905.    if (strlen(ap->subject) >= 3 &&
  11906.        (!memcmp(ap->subject,"Re:",3) ||
  11907.         !memcmp(ap->subject,"re:",3) ||
  11908.         !memcmp(ap->subject,"RE:",3)))   strcpy(mail_subject,"");
  11909.    else                                  strcpy(mail_subject,"Re: ");
  11910.    strncat(mail_subject, ap->subject, sizeof(mail_subject));
  11911.  }
  11912.  else strcpy(mail_subject,"");
  11913.  
  11914.  (void)NNMivput(np,"NNMAILTO ",to_whom_to_reply(np,ap),-1);
  11915.  (void)NNMivput(np,"NNMAILOT ",(ap ? ap->from : "")   ,-1);
  11916.  (void)NNMivput(np,"NNMAILSJ ",mail_subject,-1);
  11917.  
  11918.  strcpy(outpdsn,"");
  11919.  
  11920.  /* Can't use this - C/370 compiler bug... */
  11921.  /* strcpy(tempdsn,ap ? "" : np->maildsn); */
  11922.  
  11923.  if (ap) strcpy(tempdsn,"");
  11924.  else    strcpy(tempdsn,np->maildsn);
  11925.  
  11926.  if (!*tempdsn) {
  11927.    if (!tmpnam(tempdsn)) {
  11928.      ERR1(
  11929. "A temporary data set name could not be created.  tmpnam() error.");
  11930.      return;
  11931.    }
  11932.    if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
  11933.      ERR2("Error trying to open temp data set: %s", tempdsn);
  11934.      return;
  11935.    }
  11936.    if (fclose(efp) < 0) {
  11937.      ERR2("Error trying to close temp data set: %s", tempdsn);
  11938.      return;
  11939.    }
  11940.    efp = NULL;
  11941.    if (!ap) strcpy(np->maildsn,tempdsn);
  11942.  }
  11943.  
  11944.  while (NNMdispl(np,"NNMQMAIL") == 0) {
  11945.  
  11946.    NNMivget(np,"NNMAILTO ",mail_to,        sizeof(mail_to)        );
  11947.    NNMivget(np,"NNMAILSJ ",mail_subject,   sizeof(mail_subject)   );
  11948.    NNMivget(np,"NNMAILRT ",nnmailrt,       sizeof(nnmailrt)       );
  11949.    NNMivget(np,"NNMAILFR ",nnmailfr,       sizeof(nnmailfr)       );
  11950.    NNMivget(np,"NNMAILSF ",signature_file, sizeof(signature_file) );
  11951.    NNMivget(np,"NNEDPROF ",edit_profile,   sizeof(edit_profile)   );
  11952.  
  11953.    (void)NNMivput(np,"NNTEMPDS ",tempdsn,-1);
  11954.  
  11955.    /* Insure that we can access the signature file, if given. */
  11956.  
  11957.    if (*signature_file) {
  11958.      if (!(sfp=fopen(signature_file,"r"))) {
  11959.        perror(signature_file);
  11960.        ERR2("Cannot open signature file %s.  Check that it is valid.",
  11961.              signature_file);
  11962.        continue;
  11963.      }
  11964.    }
  11965.    else sfp = NULL;
  11966.  
  11967.    /* Fill temporary data set with message to which we are replying,
  11968.     * if this is a REPLY request,
  11969.     * and the contents of the signature file if any.
  11970.     */
  11971.  
  11972.    if (!filled) {
  11973.      if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
  11974.        ERR2("Error trying to open temp data set: %s", tempdsn);
  11975.        continue;
  11976.      }
  11977.      if (ap) {
  11978.        np->extract_file            = efp;
  11979.        np->extract_appending       = FALSE;
  11980.        np->extract_separator_line  = FALSE;
  11981.        np->extract_tab_expanding   = TRUE;
  11982.        np->following_up            = TRUE;
  11983.        fprintf(efp, "In article %s,\n%s writes:\n\n",
  11984.                     ap->message_id, ap->from);
  11985.        (void)NNMxtx(np,ap,FALSE);            /* Extract article text */
  11986.        np->following_up            = FALSE;
  11987.        if (ferror(efp)) {
  11988.          ERR2("Error trying to write to temp data set: %s", tempdsn);
  11989.          continue;
  11990.        } 
  11991.      }
  11992.  
  11993.      if (sfp) {
  11994.        fprintf(efp,"\n--\n",efp);
  11995.        if (ferror(efp)) np->extract_write_error = TRUE;
  11996.        for (;;) {
  11997.          fgets(sigline,sizeof(sigline),sfp);
  11998.          if (ferror(sfp)) {
  11999.            ERR2(
  12000.   "Cannot read from signature file %s.  Check that it is valid.",
  12001.                 signature_file);
  12002.            break;
  12003.          }
  12004.          if (feof(sfp)) break;
  12005.          if ((cp=strchr(sigline,'\n'))) *cp = '\0';
  12006.          l = strlen(sigline);
  12007.          fwrite(sigline,(l>251 ? 251 : l),1,efp);
  12008.          if (ferror(efp)) {
  12009.            np->extract_write_error = TRUE; break;
  12010.          }
  12011.          if (fputc('\n',efp) == EOF) {
  12012.            np->extract_write_error = TRUE; break;
  12013.          }
  12014.        } 
  12015.        (void)fclose(sfp);
  12016.        if (ferror(efp)) {
  12017.          ERR2("Error trying to write to temp data set: %s", tempdsn);
  12018.          continue;
  12019.        } 
  12020.      }
  12021.      if (fclose(efp) < 0) {
  12022.        ERR2("Error trying to close temp data set: %s", tempdsn);
  12023.        continue;
  12024.      }
  12025.      filled = TRUE;
  12026.    }
  12027.  
  12028.    efp = NULL;
  12029.  
  12030. #ifndef I370
  12031.    sprintf(editstr,"EDIT DATASET(%s) PROFILE(%s)",tempdsn,edit_profile);
  12032. #else
  12033.    sprintf(editstr, "EDIT DATASET('%s') PROFILE(%s)",
  12034.            tempdsn+4, edit_profile);
  12035. #endif
  12036.  
  12037.    edit_error = FALSE;
  12038.  
  12039.    (void)NNMispf(np,editstr);
  12040.    switch (np->ispfrc) {
  12041.      case 0:  edit_error = FALSE;            break;
  12042.      case 4:  ERR1(
  12043. "Edit ended without SAVE, mailing cancelled.  Reenter and SAVE to mail."
  12044.                   );                         continue;
  12045.      default: edit_error = TRUE;             break;
  12046.    }
  12047.  
  12048.    if (edit_error) continue;
  12049.  
  12050.    /* Confirm mailing. */
  12051.  
  12052.    (void)NNMispf (np,"ADDPOP ");
  12053.    display_rc = NNMdispl(np,"NNMPCONM");
  12054.    (void)NNMispf (np,"REMPOP ");
  12055.    (void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
  12056.    if (display_rc > 0) continue;
  12057.    if (*zcmd == 'c' || *zcmd == 'C') {
  12058.      (void)NNMivput(np,"ZCMD ","",-1);
  12059.      ERR1("Mailing cancelled by user.  Reenter EDIT and SAVE to mail.");
  12060.      return;
  12061.    }
  12062.  
  12063.    if (!(efp = fopen(tempdsn,"r"))) {
  12064.      ERR2("Error trying to open temp data set: %s", tempdsn);
  12065.      continue;
  12066.    }
  12067.  
  12068.    /* Get current date and time, and generate a message id from it.
  12069.     * If the message id is a duplicate, loop around until it isn't.
  12070.     */
  12071.  
  12072.    do {
  12073.  
  12074.      time(<ime);
  12075.      now = localtime(<ime);
  12076.      strftime(datestr,sizeof(datestr)-1,"%a, %d %b %Y %H:%M %Z",now);
  12077.      strftime(midstr, sizeof(midstr)-1, "%Y%m%d%H%M%S",         now);
  12078.  
  12079.      sprintf(mail_message_id,"<%s%s@%s>",
  12080.                              midstr, zuser, np->client_hostname);
  12081.  
  12082.    } while (EQUAL(mail_message_id,np->messageid));
  12083.  
  12084.    strcpy(np->messageid,mail_message_id);
  12085.  
  12086.    if (!*outpdsn) {
  12087.      if (!tmpnam(outpdsn)) {
  12088.      ERR1(
  12089. "A temporary data set name could not be created.  tmpnam() error."
  12090.          );
  12091.        continue;
  12092.      }
  12093.    }
  12094.  
  12095.    if (!(mfp = OPEN_TEXT_FILE_FOR_WRITE(outpdsn))) {
  12096.      ERR2("Error trying to open temp data set: %s", outpdsn);
  12097.      continue;
  12098.    }
  12099.  
  12100.    do {
  12101.  
  12102.      if (*nnmailfr)
  12103.           sprintf(mail_from,"%s@%s (%s)",
  12104.                             zuser, np->client_hostname, nnmailfr);
  12105.      else sprintf(mail_from,"%s@%s",
  12106.                             zuser, np->client_hostname);
  12107.  
  12108.      fprintf(mfp,"From: %s\n",       mail_from);
  12109.      fprintf(mfp,"To: %s\n",         mail_to);
  12110.      fprintf(mfp,"Subject: %s\n",    mail_subject);
  12111.      fprintf(mfp,"Date: %s\n",       datestr);
  12112.      fprintf(mfp,"Message-ID: %s\n", mail_message_id);
  12113.  
  12114.      /* insert optional headers here */
  12115.  
  12116.      if (*nnmailrt) {
  12117.        fprintf(mfp,"Reply-to: %s\n", nnmailrt);
  12118.      }
  12119.  
  12120.      fprintf(mfp,"Sender: MVS NNTP News Reader <%s@%s>\n",
  12121.                  NNMVS_NAME, np->client_hostname);
  12122.  
  12123.      if (ap) {
  12124.     /*
  12125.      * Uncomment this section when a references field in the
  12126.      * newsarticle struct is added.  Will require total recompilation
  12127.      *
  12128.      * if (ap->references)
  12129.      *  sprintf(np->nntp_command,"References: %s %s\n",
  12130.      *          ap->references, ap->message_id);
  12131.      * else
  12132.      */
  12133.        fprintf(mfp,"References: %s\n",ap->message_id);
  12134.      }
  12135.  
  12136.      /* By rights the following should be a null line.
  12137.       * However, C/370 always makes it a single blank anyhow,
  12138.       * and even if it were a null line (as SAS/C does),
  12139.       * UCLA/MAIL would break.  Hence, make it a single blank.
  12140.       */ 
  12141.  
  12142.      fprintf(mfp," \n");
  12143.  
  12144.      while (!feof(efp) && !ferror(efp)) {
  12145.        fgets(mailline,sizeof(mailline),efp);
  12146.        if (feof(efp)) break;
  12147.        if (ferror(efp)) break;
  12148.        if (*mailline && mailline[l=strlen(mailline)-1] == '\n')
  12149.           mailline[l] = '\0';
  12150.        fprintf(mfp,"%s\n",mailline);
  12151.      }
  12152.  
  12153.      fclose(mfp);
  12154.  
  12155. #ifndef I370
  12156.      sprintf(mail_command,"NNMMAIL %s %s",outpdsn,mail_to);
  12157. #else
  12158.      sprintf(mail_command,"NNMMAIL '%s' %s",outpdsn+4,mail_to);
  12159. #endif
  12160.  
  12161.      if (NNMtso(mail_command) != 0) {
  12162.        ERR1("Mail failed.  Failure trying to send your message.");
  12163.        mail_error = TRUE;
  12164.      }
  12165.  
  12166.      remove(outpdsn);
  12167.  
  12168.      break;
  12169.  
  12170.    } while(FALSE); /* one-time DO so I can break out of it */
  12171.  
  12172.    if (!mail_error) {
  12173.      (void)NNMivput(np,"NNMAILID ",mail_message_id,-1);
  12174.      WARN1("Your mail message has been sent, presumably successfully.");
  12175.      break;
  12176.    }
  12177.  
  12178.  }
  12179.  
  12180.  if (!efp) return;
  12181.  
  12182.  if (ferror(efp)) {
  12183.    ERR2("Error trying to read from temp data set: %s", tempdsn);
  12184.  }
  12185.  
  12186.  if (fclose(efp) < 0) {
  12187.    ERR2("Error trying to close temp data set: %s", tempdsn);
  12188.  }
  12189.  
  12190.  if (ap) {
  12191.    if (remove(tempdsn) < 0) {
  12192.      ERR2("Error trying to delete temp data set: %s", tempdsn);
  12193.    }
  12194.  }
  12195.  
  12196.  return; 
  12197. }
  12198.  
  12199. ./   ADD NAME=NNMDMENU,SSI=01010000
  12200.  
  12201.  /********************************************************************/
  12202.  /*                                                                  */
  12203.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  12204.  /*                                                                  */
  12205.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  12206.  /*                                                                  */
  12207.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  12208.  /* including the implied warranties of merchantability and fitness, */
  12209.  /* are expressly denied.                                            */
  12210.  /*                                                                  */
  12211.  /* Provided this copyright notice is included, this software may    */
  12212.  /* be freely distributed and not offered for sale.                  */
  12213.  /*                                                                  */
  12214.  /* Changes or modifications may be made and used only by the maker  */
  12215.  /* of same, and not further distributed.  Such modifications should */
  12216.  /* be mailed to the author for consideration for addition to the    */
  12217.  /* software and incorporation in subsequent releases.               */
  12218.  /*                                                                  */
  12219.  /********************************************************************/
  12220.  
  12221. #pragma  csect(code,  "NN@DMENU")
  12222. #pragma  csect(static,"NN$DMENU")
  12223. #include "nn.h"
  12224.  
  12225. /****** Report invalid or unsupported selection. *********************/
  12226.  
  12227. static Bool
  12228. display_invalid_selection(np)
  12229. Rstruc nncb *np;
  12230. {
  12231.  ERR1("Your selection is not valid.  Please choose an available one.");
  12232.  return FALSE;
  12233. }
  12234.  
  12235. /****** Option.....set user options. *********************************/
  12236.  
  12237. static Bool
  12238. display_set_options(np)
  12239. Rstruc nncb *np;
  12240. {
  12241.  NNMdsopt(np,NULL);
  12242.  return FALSE;
  12243. }
  12244.  
  12245. /****** Option.....execute NNTP commands. ****************************/
  12246.  
  12247. static Bool
  12248. display_nntp(np)
  12249. Rstruc nncb *np;
  12250. {
  12251.  NNMdnntp(np,NULL);
  12252.  return FALSE;
  12253. }
  12254.  
  12255. /****** Option.....list ALL newsgroups from NEWSRC file. *************/
  12256.  
  12257. static Bool
  12258. display_all_from_newsrc(np)
  12259. Rstruc nncb        *np;
  12260. {
  12261.  
  12262.  if (np->newsgroup_order == NNTP_LIST_ORDER)
  12263.     np->newsgroup_order = ALPHABETICAL_ORDER;
  12264.  np->show_all_newsgroups = TRUE;
  12265.  return NNMvng(np);                           /* View newsgroups */
  12266. }
  12267.  
  12268. /****** Option.....list REGISTERED newsgroups from NEWSRC file. ******/
  12269.  
  12270. static Bool
  12271. display_reg_from_newsrc(np)
  12272. Rstruc nncb        *np;
  12273. {
  12274.  char               nnrgans[4];
  12275.  int                prc;
  12276.  Rstruc newsgroup  *gp;
  12277.  struct countdown   cd;
  12278.  
  12279.  /* Before viewing the newsgroup list, go through all the newsgroups
  12280.   * and get the status of each one by selecting it.
  12281.   * This is controlled by the NNREGNNG variable if an option was
  12282.   * preselected and Y or N was specified for REGISTERSTATUS.
  12283.   */
  12284.  
  12285.  nnrgans[0] = 'P';
  12286.  if (np->preselection) {
  12287.    switch (np->nnregnng[0]) {
  12288.      case 'N': nnrgans[0] = 'N'; break;
  12289.      case 'Y': nnrgans[0] = 'Y'; break;
  12290.    }
  12291.  }
  12292.  
  12293.  if (nnrgans[0] == 'P') {
  12294.  
  12295.    /* Display panel asking if user really wants to do this. */
  12296.  
  12297.    (void)NNMispf(np,"ADDPOP");
  12298.    prc = NNMdispl(np,"NNMPGREG");
  12299.    (void)NNMispf(np,"REMPOP");
  12300.    if (prc > 0) return FALSE;  /* see if user pressed END */
  12301.    (void)NNMivget(np,"NNRGANS ",nnrgans,sizeof(nnrgans));
  12302.  
  12303.  }
  12304.  
  12305.  if (nnrgans[0] == 'Y') {
  12306.    if (np->updatefreq >= 0) {
  12307.      cd.do_update = TRUE;
  12308.      cd.done      = 0;
  12309.      cd.to_do     = 0;
  12310.      for (gp=np->first_newsgroup;gp;gp=gp->next) {
  12311.        if (gp->registered) cd.to_do++;
  12312.      }
  12313.    }
  12314.    for (gp=np->first_newsgroup;gp;gp=gp->next) {
  12315.      if (gp->registered) {
  12316.        if (np->updatefreq >= 0) {
  12317.          (void)NNMivput(np,"NNLGROUP ",gp->name,-1);
  12318.          /*
  12319.           * (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  12320.           * (void)NNMispf(np,"DISPLAY PANEL(NNMLRETG)");
  12321.           */
  12322.          NNMupdt(np,&cd,np->updatefreq > 0 ? "NNMLRET2" : "NNMLRET3");
  12323.        } 
  12324.        NNMdng(np,gp,NULL);        /* do newsgroup by address */
  12325.      }
  12326.    }
  12327.  }
  12328.  
  12329.  if (np->newsgroup_order == NNTP_LIST_ORDER)
  12330.     np->newsgroup_order = ALPHABETICAL_ORDER;
  12331.  np->show_all_newsgroups = FALSE;
  12332.  return NNMvng(np);                           /* View newsgroups */
  12333. }
  12334.  
  12335. /****** Option.....list all newsgroups. ******************************/
  12336.  
  12337. static Bool
  12338. list_all_newsgroups(np)
  12339. Rstruc nncb       *np;
  12340. {
  12341.  return NNMdlang(np,LIST_ALL);
  12342. }
  12343.  
  12344. /****** Option.....list all newsgroups with fake disconnect. *********/
  12345.  
  12346. static Bool
  12347. list_all_newsgroups_with_fake_disconnect(np)
  12348. Rstruc nncb       *np;
  12349. {
  12350.  return NNMdlang(np,LIST_ALL_DISCONNECT);
  12351. }
  12352.  
  12353. /****** Option.....list new newsgroups. ******************************/
  12354.  
  12355. static Bool
  12356. list_new_newsgroups(np)
  12357. Rstruc nncb       *np;
  12358. {
  12359.  return NNMdlang(np,LIST_NEW);
  12360. }
  12361.  
  12362. /****** Option.....retrieve articles from specified newsgroup. *******/
  12363.  
  12364. static Bool
  12365. display_specific_newsgroup(np)
  12366. Rstruc nncb       *np;
  12367. {
  12368.  Rstruc newsgroup *gp;
  12369.  
  12370.  np->newsgroup_selected = FALSE;
  12371.  
  12372.  /* The ISPF variable NNGROUPI contains the name of the newsgroup. */
  12373.  
  12374.  if (NNMivget(np,"NNGROUPI ",np->nngroup,sizeof(np->nngroup))) {
  12375.  
  12376.    lowercase_in_place(np->nngroup);
  12377.  
  12378.    (void)NNMivput(np,"NNGROUP ",np->nngroup,-1);
  12379.  
  12380.    gp = NNMdng(np,NULL,np->nngroup);    /* do newsgroup by name */
  12381.    if (!gp) {
  12382.      (void)NNMivput(np,"NNCURSOR ","NNGROUPI ",8);
  12383.      return FALSE;
  12384.    }
  12385.  
  12386.    np->show_all_articles       = TRUE;
  12387.    np->bypass_header_retrieval = FALSE;
  12388.    np->unread_articles_only    = FALSE;
  12389.  
  12390.    (void)NNMvar(np,gp);              /* View articles */
  12391.  }
  12392.  
  12393.  return TRUE;
  12394. }
  12395.  
  12396. /****** Display menu. ************************************************/
  12397.  
  12398. enum display_retval
  12399. NNMdmenu(np,selfunp)
  12400. Rstruc nncb   *np;
  12401. Bool        (**selfunp)();
  12402. {
  12403.  char        zcmd[72];
  12404.  char        new_nnserver[MAXHOSTNAMELEN];
  12405.  Bool        server_changed = FALSE;
  12406.  
  12407.  *selfunp = NULL;
  12408.  
  12409.  if (np->preselection) {
  12410.    zcmd[0] = toupper(np->preselection);
  12411.    np->preselection = SELECTION_EXIT;
  12412.    (void)NNMispf(np,
  12413.                  "VGET (NNSERVER NNNEWSRC NNREGNNG NNGROUPI) PROFILE");
  12414.  }
  12415.  else {
  12416.  
  12417.    (void)NNMispf(np,"CONTROL DISPLAY REFRESH");
  12418.  
  12419.    (void)NNMdispl(np,"NNM     ");
  12420.    if (np->ispfrc > 8) return DISPLAY_FAILURE;
  12421.    if (np->ispfrc > 0) return DISPLAY_EXIT;
  12422.    if (!NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd))) return DISPLAY_ERROR;
  12423.  }
  12424.  
  12425.  if (!NNMivget(np,"NNSERVER ",new_nnserver,MAXHOSTNAMELEN)
  12426.   || !NNMivget(np,"NNREGNNG ",np->nnregnng,sizeof(np->nnregnng))) {
  12427.    np->preselection = '\0';
  12428.    return DISPLAY_ERROR;
  12429.  }
  12430.  
  12431.  /* Note: selection functions return Bool value indicating whether
  12432.   *       to rewrite NEWSRC file (TRUE) or not (FALSE).
  12433.   *       See NNMMAIN for implementation of this.
  12434.   */
  12435.  
  12436.  switch (zcmd[0]) {
  12437.    case SELECTION_ALL:   *selfunp = display_all_from_newsrc;    break;
  12438.    case SELECTION_REG:   *selfunp = display_reg_from_newsrc;    break;
  12439.    case SELECTION_GROUP: *selfunp = display_specific_newsgroup; break;
  12440.    case SELECTION_LIST:  *selfunp = list_all_newsgroups;        break;
  12441.    case SELECTION_NEWG:  *selfunp = list_new_newsgroups;        break;
  12442.    case SELECTION_NNTP:  *selfunp = display_nntp;               break;
  12443.    case SELECTION_OPTS:  *selfunp = display_set_options;        break;
  12444.    case SELECTION_EXIT:  return DISPLAY_EXIT;
  12445.    case SELECTION_LIST_DISCONNECT:
  12446.                  *selfunp = list_all_newsgroups_with_fake_disconnect;
  12447.                  break;
  12448.    default:              *selfunp = display_invalid_selection;
  12449.                          np->preselection = '\0';
  12450.                          return DISPLAY_REPEAT;
  12451.  };
  12452.  
  12453.  /* If user typed a different server name, or this is the first time,
  12454.     connect to the requested server. */
  12455.  
  12456.  if (UNEQUAL(new_nnserver,np->nnserver)) {
  12457.    server_changed = TRUE;
  12458.  }
  12459.  if (!np->connected_to_server || np->connection_broken ||
  12460.      server_changed) {
  12461.    strcpy(np->nnserver,new_nnserver);
  12462.    if (!NNMconn(np)) {                  /* Connect to news server */
  12463.      (void)NNMivput(np,"NNCURSOR ","NNSERVER ",8);
  12464.      *selfunp = NULL;
  12465.      np->preselection = '\0';
  12466.      return DISPLAY_ERROR;
  12467.    }
  12468.  }
  12469.  
  12470.  return DISPLAY_REPEAT;
  12471. }
  12472.  
  12473. ./   ADD NAME=NNMDNG,SSI=010F0052
  12474.  
  12475.  /********************************************************************/
  12476.  /*                                                                  */
  12477.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  12478.  /*                                                                  */
  12479.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  12480.  /*                                                                  */
  12481.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  12482.  /* including the implied warranties of merchantability and fitness, */
  12483.  /* are expressly denied.                                            */
  12484.  /*                                                                  */
  12485.  /* Provided this copyright notice is included, this software may    */
  12486.  /* be freely distributed and not offered for sale.                  */
  12487.  /*                                                                  */
  12488.  /* Changes or modifications may be made and used only by the maker  */
  12489.  /* of same, and not further distributed.  Such modifications should */
  12490.  /* be mailed to the author for consideration for addition to the    */
  12491.  /* software and incorporation in subsequent releases.               */
  12492.  /*                                                                  */
  12493.  /********************************************************************/
  12494.  
  12495. #pragma  csect(code,  "NN@DNG  ")
  12496. #pragma  csect(static,"NN$DNG  ")
  12497. #include "nn.h"
  12498.  
  12499. /****** Process newsgroup by name or address. ************************/
  12500.  
  12501. struct newsgroup *
  12502. NNMdng(np,gp,group)
  12503. Rstruc nncb         *np;
  12504. Rstruc newsgroup    *gp;
  12505. char                *group;
  12506. {
  12507.  int                 group_article_count         = NO_VALUE;
  12508.  int                 group_first_article_number  = NO_VALUE;
  12509.  int                 group_last_article_number   = NO_VALUE;
  12510.  char                group_name[GROUP_NAME_SIZE] = "";
  12511.  
  12512.  /* Tell the server to select the requested newsgroup. */
  12513.  
  12514.  if (!NNMestng(np,gp ? gp->name : group)) /* Establish newsgroup */
  12515.     return NULL;
  12516.  
  12517.  /* From the response to the "GROUP xxx" NNTP selection request,
  12518.     extract the number of articles and the numbers of the
  12519.     first and last articles, as well as the actual name. */
  12520.  
  12521.  if (4 != sscanf(np->nntp_message_text, "%d %d %d %s",
  12522.                               &group_article_count,
  12523.                               &group_first_article_number,
  12524.                               &group_last_article_number,
  12525.                                group_name)) {
  12526.    NNMrbfm(np);   /* Report bad format message */
  12527.    return NULL;
  12528.  }
  12529.  
  12530.  lowercase_in_place(group_name);
  12531.  
  12532.  if (!gp) gp = NNMaddng(np,group_name);   /* Add newsgroup */
  12533.  
  12534.  OffNoSuchGroup(gp);
  12535.  OffGroupError(gp);
  12536.  
  12537.  /* Logic:
  12538.   * This code sets up a newsgroup from NNTP GROUP.
  12539.   * They are already found in .newsrc (unless new newsgroups),
  12540.   * and may or may not have already been LISTed.
  12541.   * So there is a possibility of an article vector existing,
  12542.   * but in most cases there won't be.
  12543.   * The overriding principle here is that the active file knows
  12544.   * best the actual range, but the GROUP command will return
  12545.   * information about missing articles at either end of the list.
  12546.   */
  12547.  
  12548.  if (GroupFromNewsrc(gp)
  12549.   || GroupFromNNTP(gp)) {          /* Adjust unread articles */
  12550.    NNMadjua(np,gp,group_article_count,
  12551.                   group_first_article_number,
  12552.                   group_last_article_number);
  12553.  }
  12554.  else {
  12555.    gp->unread_count = group_article_count;
  12556.  }
  12557.  
  12558.  /* Allocate article vector */
  12559.  
  12560.  NNMallav(np,gp,group_first_article_number,group_last_article_number);
  12561.  
  12562.  gp->article_count = group_article_count;
  12563.  
  12564.  if (gp->article_vector) {
  12565.    if (gp->low_number == 0
  12566.     || gp->low_number > group_first_article_number
  12567.     || !GroupFromNNTP(gp)) {
  12568.        gp->low_number = group_first_article_number;
  12569.    }
  12570.    if (gp->high_number == 0
  12571.     || gp->high_number < group_last_article_number) {
  12572.        gp->high_number = group_last_article_number;
  12573.    }
  12574.  }
  12575.  
  12576.  /*
  12577.   *
  12578.   * Don't know why this was here, but it is causing a bug with
  12579.   * registering new groups, so take it out.
  12580.   *
  12581.   * if (!GroupFromNewsrc(gp)) {
  12582.   *   gp->registered = 0;
  12583.   * }
  12584.   */
  12585.  
  12586.  if (np->show_all_articles) SetGroupSelected(gp);
  12587.  else                       SetGroupSelectedUnread(gp);
  12588.  
  12589.  return gp;
  12590. }
  12591. ./   ADD NAME=NNMDNNTP,SSI=01000015
  12592.  
  12593.  /********************************************************************/
  12594.  /*                                                                  */
  12595.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  12596.  /*                                                                  */
  12597.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  12598.  /* including the implied warranties of merchantability and fitness, */
  12599.  /* are expressly denied.                                            */
  12600.  /*                                                                  */
  12601.  /* Provided this copyright notice is included, this software may    */
  12602.  /* be freely distributed and not offered for sale.                  */
  12603.  /*                                                                  */
  12604.  /* Changes or modifications may be made and used only by the maker  */
  12605.  /* of same, and not further distributed.  Such modifications should */
  12606.  /* be mailed to the author for consideration for addition to the    */
  12607.  /* software and incorporation in subsequent releases.               */
  12608.  /*                                                                  */
  12609.  /********************************************************************/
  12610.  
  12611. #pragma  csect(code,  "NN@DNNTP")
  12612. #pragma  csect(static,"NN$DNNTP")
  12613. #include "nn.h"
  12614.  
  12615. /****** Option ... process native NNTP protocol commands. ************/
  12616.  
  12617. void
  12618. NNMdnntp(np,command)
  12619. Rstruc nncb *np;
  12620. char        *command;
  12621. {
  12622.  
  12623.  if (command && *command) {
  12624.    strncpy(np->nntp_command, command, CLIENT_BUF_MSGSIZE);
  12625.    NNMnntp(np);                    /* execute NNTP commands */
  12626.  }
  12627.  
  12628.  else while (NNMdispl(np,"NNM0    ") == 0 && !np->quit) {
  12629.  
  12630.    (void)NNMivget(np,"NNCMD ",np->nntp_command,CLIENT_BUF_MSGSIZE);
  12631.    if (np->ispfrc == 0) NNMnntp(np); /* execute NNTP commands */
  12632.  
  12633.    if (np->quit) break;
  12634.  }
  12635.  
  12636.  return; 
  12637. }
  12638.  
  12639. ./   ADD NAME=NNMDOIT,SSI=01040002
  12640.  
  12641.  /********************************************************************/
  12642.  /*                                                                  */
  12643.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  12644.  /*                                                                  */
  12645.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  12646.  /* including the implied warranties of merchantability and fitness, */
  12647.  /* are expressly denied.                                            */
  12648.  /*                                                                  */
  12649.  /* Provided this copyright notice is included, this software may    */
  12650.  /* be freely distributed and not offered for sale.                  */
  12651.  /*                                                                  */
  12652.  /* Changes or modifications may be made and used only by the maker  */
  12653.  /* of same, and not further distributed.  Such modifications should */
  12654.  /* be mailed to the author for consideration for addition to the    */
  12655.  /* software and incorporation in subsequent releases.               */
  12656.  /*                                                                  */
  12657.  /********************************************************************/
  12658.  
  12659. #pragma  csect(code,  "NN@DOIT ")
  12660. #pragma  csect(static,"NN$DOIT ")
  12661. #include "nn.h"
  12662.  
  12663. /****** Do it (whatever it is) to the article. ***********************/
  12664.  
  12665. void
  12666. NNMdoit(np,ap,whatfor)
  12667. Rstruc nncb          *np;
  12668. Rstruc newsarticle   *ap;
  12669. Fool                  whatfor;
  12670. {
  12671.  Rstruc newsgroup    *gp;
  12672.  VARK                *vp;
  12673.  
  12674.  gp = np->current_newsgroup;
  12675.  vp = &GETVARK(gp,ap->number);
  12676.  
  12677.  switch (whatfor) {
  12678.    case 'S':
  12679.             NNMvtx(np,gp,ap);                 /* View text */
  12680.             NNMmarr(np,gp,vp);                /* Make article read */
  12681.             ap->action = READ;
  12682.             break;
  12683.    case 'E':
  12684.             np->extract_write_error = FALSE;
  12685.             np->extract_close_error = FALSE;
  12686.             np->printing            = FALSE;
  12687.             if (NNMxtx(np,ap,TRUE)) {         /* Extract text */
  12688.               if (!np->extract_write_error &&
  12689.                   !np->extract_close_error) {
  12690.                 NNMmarr(np,gp,vp);            /* Make article read */
  12691.                 ap->action = EXTRACTED;
  12692.               }
  12693.             }
  12694.             break;
  12695.    case 'P':
  12696.             np->extract_write_error = FALSE;
  12697.             np->extract_close_error = FALSE;
  12698.             np->printing            = TRUE;
  12699.             if (NNMxtx(np,ap,TRUE)) {         /* Print text */
  12700.               if (!np->extract_write_error &&
  12701.                   !np->extract_close_error) {
  12702.                 NNMmarr(np,gp,vp);            /* Make article read */
  12703.                 ap->action = PRINTED;
  12704.               }
  12705.             }
  12706.             break;
  12707.    case 'F':
  12708.             NNMdpost(np,gp,ap);               /* Post followup */
  12709.             ap->action = RETRIEVED;
  12710.             break;
  12711.    case 'R':
  12712.             NNMdmail(np,gp,ap);               /* Mail reply */
  12713.             ap->action = RETRIEVED;
  12714.             break;
  12715.    case 'C':
  12716.             if (NNMdcan(np,gp,ap)) {          /* Cancel article */
  12717.               ap->action = CANCELLED;
  12718.             }
  12719.             break;
  12720.  }
  12721.  
  12722.  np->top_article = ap->number;
  12723.  np->top_sorted_article = np->current_sortvark;
  12724.  
  12725.  return; 
  12726. }
  12727.  
  12728. ./   ADD NAME=NNMDPOST,SSI=01010016
  12729.  
  12730.  /********************************************************************/
  12731.  /*                                                                  */
  12732.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  12733.  /*                                                                  */
  12734.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  12735.  /*                                                                  */
  12736.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  12737.  /* including the implied warranties of merchantability and fitness, */
  12738.  /* are expressly denied.                                            */
  12739.  /*                                                                  */
  12740.  /* Provided this copyright notice is included, this software may    */
  12741.  /* be freely distributed and not offered for sale.                  */
  12742.  /*                                                                  */
  12743.  /* Changes or modifications may be made and used only by the maker  */
  12744.  /* of same, and not further distributed.  Such modifications should */
  12745.  /* be mailed to the author for consideration for addition to the    */
  12746.  /* software and incorporation in subsequent releases.               */
  12747.  /*                                                                  */
  12748.  /********************************************************************/
  12749.  
  12750. #pragma  csect(code,  "NN@DPOST")
  12751. #pragma  csect(static,"NN$DPOST")
  12752. #include "nn.h"
  12753.  
  12754. #define NEWSGROUPS_LENGTH   256-sizeof("Newsgroups: ")
  12755. #define SUBJECT_LENGTH      256-sizeof("Subject: ")
  12756. #define PATH_LENGTH         256-sizeof("Path: ")
  12757. #define FROM_LENGTH         256-sizeof("From: ")
  12758. #define REPLY_TO_LENGTH     256-sizeof("Reply-to: ")
  12759. #define FOLLOWUP_TO_LENGTH  256-sizeof("Followup-to: ")
  12760.  
  12761. #define HEADCAT(A,B)        strncat((A),(B),NEWSGROUPS_LENGTH)
  12762.  
  12763. /****** Make a comma delimited list out of user's newsgroup spec. ****/
  12764.  
  12765. static void
  12766. make_comma_delimited_list(instring,outstring)
  12767. char                *instring;
  12768. char                *outstring;
  12769. {
  12770.  char               *icp;
  12771.  char               *ocp;
  12772.  Bool                between;
  12773.  
  12774.  between = FALSE;
  12775.  icp = instring + strspn(instring," ,");
  12776.  ocp = outstring;
  12777.  do {
  12778.    switch (*icp) {
  12779.      case '\0': *ocp = '\0'; break;
  12780.      case ' ' :
  12781.      case ',' :  between = TRUE; break;
  12782.      default  :  if (between) {
  12783.                    between = FALSE;
  12784.                    *(ocp++) = ',';
  12785.                  }
  12786.                  *(ocp++) = tolower(*icp);
  12787.                  break;
  12788.    }
  12789.  } while (*icp++);
  12790.  
  12791. }
  12792.  
  12793. /****** Collect additional article headers that we may need. *********/
  12794.  
  12795. static void
  12796. get_more_headers(np,ap,newsgroups,followup_to)
  12797. Rstruc nncb          *np;
  12798. Rstruc newsarticle   *ap;
  12799. char                 *newsgroups;
  12800. char                 *followup_to;
  12801. {
  12802.  struct textline     *tp;
  12803.  struct texthdr      *thp;
  12804.  char                *cp;
  12805.  char                *newp;
  12806.  char                *colonp;
  12807.  int                  header_index;
  12808.  char                 the_header[INTERNET_SIZE];
  12809.  
  12810.  strcpy(newsgroups,  "");
  12811.  strcpy(followup_to, "");
  12812.  
  12813.  if (!ap) return;
  12814.  
  12815.  /* Grovel through headers looking for what we want.  */
  12816.  
  12817.  newp = NULL;
  12818.  thp = &ap->thdr;
  12819.  strcpy(the_header,"");
  12820.  for (tp=thp->first_text_line; tp; tp=tp->next) {
  12821.    if (tp->text[0] == '\0') break;
  12822.    if (tp->text[0] == ' '
  12823.     || tp->text[0] == '\t') {
  12824.      cp = skip_whitespace(tp->text);
  12825.      if (*cp == '\0') break;
  12826.    }
  12827.    else {
  12828.      header_index = 0;
  12829.      colonp = strchr(tp->text,':');
  12830.      if (!colonp) break;
  12831.      strcpy(the_header,"");
  12832.      for (cp = tp->text;cp<colonp;cp++) {
  12833.        the_header[header_index++] = toupper(*cp);
  12834.      }
  12835.      the_header[header_index] = '\0';
  12836.      cp = skip_whitespace(colonp+1);
  12837.    }
  12838.    if      (EQUAL(the_header,"NEWSGROUPS"  )) HEADCAT(newsgroups, cp);
  12839.    else if (EQUAL(the_header,"FOLLOWUP-TO" )) HEADCAT(followup_to,cp);
  12840.  }
  12841.  
  12842.  lowercase_and_strip_trailing_in_place(newsgroups);
  12843.  lowercase_and_strip_trailing_in_place(followup_to);
  12844.  
  12845.  return; 
  12846.  
  12847. }
  12848.  
  12849. /****** Post a news article. *****************************************/
  12850.  
  12851. void
  12852. NNMdpost(np,gp,ap)
  12853. Rstruc nncb         *np;
  12854. Rstruc newsgroup    *gp;
  12855. Rstruc newsarticle  *ap;
  12856. {
  12857.  Bool                filled       = FALSE;
  12858.  Bool                edit_error   = FALSE;
  12859.  Bool                post_error   = FALSE;
  12860.  int                 l;
  12861.  int                 display_rc;
  12862.  char               *postdefault  = NULL;
  12863.  char               *lp;
  12864.  char               *cp;
  12865.  FILE               *efp          = NULL;
  12866.  FILE               *sfp          = NULL;
  12867.  struct tm          *now;
  12868.  time_t              ltime;
  12869.  char                datestr [64];
  12870.  char                midstr  [64];
  12871.  char                zuser   [ 9];
  12872.  char                temp    [12];
  12873.  char                tempdsn [L_tmpnam];
  12874.  char                editstr [40+L_tmpnam];
  12875.  char                edit_profile     [  9];
  12876.  char                signature_file   [ 64];
  12877.  char                post_message_id  [128];
  12878.  char                zcmd             [ 81];
  12879.  char                post_subject     [SUBJECT_LENGTH];
  12880.  char                post_path        [PATH_LENGTH];
  12881.  char                post_newsgroups  [NEWSGROUPS_LENGTH];
  12882.  char                post_followup_to [NEWSGROUPS_LENGTH];
  12883.  char                post_from        [FROM_LENGTH];
  12884.  char                nnpostng         [NEWSGROUPS_LENGTH];
  12885.  char                nnpostrt         [REPLY_TO_LENGTH];
  12886.  char                nnpostfo         [FOLLOWUP_TO_LENGTH];
  12887.  char                nnpostfr         [FROM_LENGTH];
  12888.  char                newsgroups       [NEWSGROUPS_LENGTH];
  12889.  char                followup_to      [NEWSGROUPS_LENGTH];
  12890.  char                postline         [260];
  12891.  char                sigline          [260];
  12892.  
  12893.  (void)NNMivget(np,"ZUSER ",zuser,sizeof(zuser));
  12894.  
  12895.  if (ap) {
  12896.    if (strlen(ap->subject) >= 3 &&
  12897.        (!memcmp(ap->subject,"Re:",3) ||
  12898.         !memcmp(ap->subject,"re:",3) ||
  12899.         !memcmp(ap->subject,"RE:",3)))   strcpy(post_subject,"");
  12900.    else                                  strcpy(post_subject,"Re: ");
  12901.    strncat(post_subject, ap->subject, sizeof(post_subject));
  12902.  }
  12903.  else strcpy(post_subject,"");
  12904.  
  12905.  sprintf(post_path,"%s!%s", np->client_hostname, zuser);
  12906.  
  12907.  (void)NNMivput(np,"NNPOSTSJ ",post_subject,-1);
  12908.  if (ap) {
  12909.    sprintf(temp,"%d",ap->number);
  12910.    (void)NNMivput(np,"NNPOSTHA ",temp,        -1);
  12911.    (void)NNMivput(np,"NNPOSTHG ",gp->name,    -1);
  12912.  }
  12913.  else {
  12914.    (void)NNMivput(np,"NNPOSTHA ","",          -1);
  12915.    (void)NNMivput(np,"NNPOSTHG ",""          ,-1);
  12916.  }
  12917.  
  12918.  /*
  12919.   * Simple-minded and wrong - newsgroups to post to = current one
  12920.   *
  12921.   * (void)NNMivput(np,"NNPOSTNG ",gp ? gp->name : "",-1);
  12922.   *
  12923.   * The correct way:  if we are following up an article, then
  12924.   * if the Followup_to header is present, use that, else
  12925.   * use the Newsgroups: header.  If not there, use the newsgroup name.
  12926.   *
  12927.   * If fresh post, use the newsgroup name.
  12928.   */
  12929.  
  12930.  if (gp) {
  12931.    if (ap) {  /* this is a followup */
  12932.      strcpy(newsgroups, "");
  12933.      strcpy(followup_to,"");
  12934.      get_more_headers(np,ap,newsgroups,followup_to);
  12935.      if      (EQUAL(followup_to,"poster")) {
  12936.        ERR1(
  12937. "Followups are directed to the poster.  Suggest you use REPLY instead."
  12938.            );
  12939.        postdefault = "";
  12940.      }
  12941.      else if (strchr(followup_to,'@')) {
  12942.        ERR1(
  12943. "Followup header contains mailing address.  Suggest you REPLY instead."
  12944.            );
  12945.        postdefault = "";
  12946.      }
  12947.      else if (*followup_to)  postdefault = followup_to;
  12948.      else if (*newsgroups)   postdefault = newsgroups;
  12949.      else                    postdefault = gp->name;
  12950.    }
  12951.    else {     /* this is a fresh posting */
  12952.      postdefault = gp->name;
  12953.    }
  12954.  }
  12955.  else {
  12956.    postdefault = "";
  12957.  }
  12958.  
  12959.  (void)NNMivput(np,"NNPOSTNG ",postdefault,-1);
  12960.  
  12961.  /* Can't use this - C/370 compiler bug... */
  12962.  /* strcpy(tempdsn,ap ? "" : np->maildsn); */
  12963.  
  12964.  if (ap) strcpy(tempdsn,"");
  12965.  else    strcpy(tempdsn,np->maildsn);
  12966.  
  12967.  if (!*tempdsn) {
  12968.    if (!tmpnam(tempdsn)) {
  12969.      ERR1(
  12970. "A temporary data set name could not be created.  tmpnam() error."
  12971.          );
  12972.      return;
  12973.    }
  12974.    if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
  12975.      ERR2("Error trying to open temp data set: %s", tempdsn);
  12976.      return;
  12977.    }
  12978.    if (fclose(efp) < 0) {
  12979.      ERR2("Error trying to close temp data set: %s", tempdsn);
  12980.      return;
  12981.    }
  12982.    efp = NULL;
  12983.    if (!ap) strcpy(np->maildsn,tempdsn);
  12984.  }
  12985.  
  12986.  while (NNMdispl(np,"NNMQPOST") == 0) {
  12987.  
  12988.    NNMivget(np,"NNPOSTNG ",nnpostng,       sizeof(nnpostng));
  12989.    NNMivget(np,"NNPOSTRT ",nnpostrt,       sizeof(nnpostrt));
  12990.    NNMivget(np,"NNPOSTFO ",nnpostfo,       sizeof(nnpostfo));
  12991.    NNMivget(np,"NNPOSTFR ",nnpostfr,       sizeof(nnpostfr));
  12992.    NNMivget(np,"NNPOSTSJ ",post_subject,   sizeof(post_subject)   );
  12993.    NNMivget(np,"NNPOSTSF ",signature_file, sizeof(signature_file) );
  12994.    NNMivget(np,"NNEDPROF ",edit_profile,   sizeof(edit_profile)   );
  12995.  
  12996.    /* Create correctly formatted newsgroup listing. */
  12997.  
  12998.    make_comma_delimited_list(nnpostng,post_newsgroups);
  12999.  
  13000.    make_comma_delimited_list(nnpostfo,post_followup_to);
  13001.  
  13002.    (void)NNMivput(np,"NNTEMPDS ",tempdsn,-1);
  13003.  
  13004.    /* Insure that we can access the signature file, if given. */
  13005.  
  13006.    if (*signature_file) {
  13007.      if (!(sfp=fopen(signature_file,"r"))) {
  13008.        perror(signature_file);
  13009.        ERR2("Cannot open signature file %s.  Check that it is valid.",
  13010.              signature_file);
  13011.        continue;
  13012.      }
  13013.    }
  13014.    else sfp = NULL;
  13015.  
  13016.    /* Fill temporary data set with message to which we are replying,
  13017.     * if this is a FOLLOWUP request,
  13018.     * and the contents of the signature file if any.
  13019.     */
  13020.  
  13021.    if (!filled) {
  13022.      if (!(efp = OPEN_TEXT_FILE_FOR_WRITE(tempdsn))) {
  13023.        ERR2("Error trying to open temp data set: %s", tempdsn);
  13024.        continue;
  13025.      }
  13026.      if (ap) {
  13027.        np->extract_file            = efp;
  13028.        np->extract_appending       = FALSE;
  13029.        np->extract_separator_line  = FALSE;
  13030.        np->extract_tab_expanding   = TRUE;
  13031.        np->following_up            = TRUE;
  13032.        fprintf(efp, "In article %s,\n%s writes:\n\n",
  13033.                     ap->message_id, ap->from);
  13034.        (void)NNMxtx(np,ap,FALSE);            /* Extract article text */
  13035.        np->following_up            = FALSE;
  13036.        if (ferror(efp)) {
  13037.          ERR2("Error trying to write to temp data set: %s", tempdsn);
  13038.          continue;
  13039.        } 
  13040.      }
  13041.      if (sfp) {
  13042.        fprintf(efp,"\n--\n",efp);
  13043.        if (ferror(efp)) np->extract_write_error = TRUE;
  13044.        for (;;) {
  13045.          fgets(sigline,sizeof(sigline),sfp);
  13046.          if (ferror(sfp)) {
  13047.            ERR2(
  13048.   "Cannot read from signature file %s.  Check that it is valid.",
  13049.                 signature_file);
  13050.            break;
  13051.          }
  13052.          if (feof(sfp)) break;
  13053.          if ((cp=strchr(sigline,'\n'))) *cp = '\0';
  13054.          l = strlen(sigline);
  13055.          fwrite(sigline,(l>251 ? 251 : l),1,efp);
  13056.          if (ferror(efp)) {
  13057.            np->extract_write_error = TRUE; break;
  13058.          }
  13059.          if (fputc('\n',efp) == EOF) {
  13060.            np->extract_write_error = TRUE; break;
  13061.          }
  13062.        } 
  13063.        (void)fclose(sfp);
  13064.        if (ferror(efp)) {
  13065.          ERR2("Error trying to write to temp data set: %s", tempdsn);
  13066.          continue;
  13067.        } 
  13068.      }
  13069.      if (fclose(efp) < 0) {
  13070.        ERR2("Error trying to close temp data set: %s", tempdsn);
  13071.        continue;
  13072.      }
  13073.      filled = TRUE;
  13074.    }
  13075.  
  13076.    efp = NULL;
  13077.  
  13078. #ifndef I370
  13079.    sprintf(editstr,"EDIT DATASET(%s) PROFILE(%s)",tempdsn,edit_profile);
  13080. #else
  13081.    sprintf(editstr, "EDIT DATASET('%s') PROFILE(%s)",
  13082.            tempdsn+4, edit_profile);
  13083. #endif
  13084.  
  13085.    edit_error = FALSE;
  13086.  
  13087.    (void)NNMispf(np,editstr);
  13088.    switch (np->ispfrc) {
  13089.      case 0:  edit_error = FALSE;      break;
  13090.      case 4:  ERR1(
  13091. "Edit ended without SAVE, posting cancelled.  Reenter and SAVE to post."
  13092.                   );                         continue;
  13093.      default: edit_error = TRUE;       break;
  13094.    }
  13095.  
  13096.    if (edit_error) continue;
  13097.  
  13098.    /* Confirm posting. */
  13099.  
  13100.    (void)NNMispf (np,"ADDPOP ");
  13101.    display_rc = NNMdispl(np,"NNMPCONP");
  13102.    (void)NNMispf (np,"REMPOP ");
  13103.    (void)NNMivget(np,"ZCMD ",zcmd,sizeof(zcmd));
  13104.    if (display_rc > 0) continue;
  13105.    if (*zcmd == 'c' || *zcmd == 'C') {
  13106.      (void)NNMivput(np,"ZCMD ","",-1);
  13107.      ERR1("Posting cancelled by user.  Reenter EDIT and SAVE to post.");
  13108.      return;
  13109.    }
  13110.  
  13111.    if (!(efp = fopen(tempdsn,"r"))) {
  13112.      ERR2("Error trying to open temp data set: %s", tempdsn);
  13113.      continue;
  13114.    }
  13115.  
  13116.    /* Start posting here.
  13117.     *
  13118.     * Me:     POST
  13119.     * Server: 340 send article to be posted.  End with <CR-LF>.<CR-LF>
  13120.     *     or: 440 posting not allowed
  13121.     * If 430...
  13122.     *
  13123.     * See RFC850 for details.
  13124.     *
  13125.     * Me:     required_header: xxx
  13126.     * ...
  13127.     * Me:     <null line>
  13128.     * Read text from tempdsn
  13129.     * Me:     <text with leading periods hacked>
  13130.     * Me:     .
  13131.     * Server: 240 article posted OK
  13132.     *     or: 441 posting failed
  13133.     */
  13134.  
  13135.     /* See RFC 1036 for full information. */
  13136.  
  13137.    /* Required headers - from, date, subject, newsgroups,
  13138.     *                    message-id, path
  13139.     */
  13140.  
  13141.    /* Optional headers - reply-to, sender, followup-to, expires, xref,
  13142.     *                    references, control, distribution, lines,
  13143.     *                    organization, keywords, summary, approved
  13144.     */
  13145.  
  13146.  
  13147.    /* Get current date and time, and generate a message id from it.
  13148.     * If the message id is a duplicate, loop around until it isn't.
  13149.     */
  13150.  
  13151.    do {
  13152.  
  13153.      time(<ime);
  13154.      now = localtime(<ime);
  13155.      strftime(datestr,sizeof(datestr)-1,"%a, %d %b %Y %H:%M %Z",now);
  13156.      strftime(midstr, sizeof(midstr)-1, "%Y%m%d%H%M%S",now);
  13157.  
  13158.      sprintf(post_message_id,"<%s%s@%s>",
  13159.                              midstr, zuser, np->client_hostname);
  13160.  
  13161.    } while (EQUAL(post_message_id,np->messageid));
  13162.  
  13163.    strcpy(np->messageid,post_message_id);
  13164.  
  13165.    do {
  13166.      strcpy(np->nntp_command,"POST");
  13167.      if (!NNMsockt(np))     break;  /* Send socket command to server */
  13168.      if (!NNMgsrvl(np,&lp)) break;  /* Get server line */
  13169.      switch (np->nntp_message_num) {
  13170.        case 340: post_error = FALSE;
  13171.                  break;
  13172.        case 440: ERR2(
  13173.          "Posting not allowed.  Server %s did not accept the post.",
  13174.                       np->nnserver);
  13175.                  post_error = TRUE;
  13176.                  break;
  13177.        default:  NNMrperr(np);       /* Report protocol error */
  13178.                  post_error = TRUE;
  13179.                  break;
  13180.      }
  13181.  
  13182.      if (post_error) break;
  13183.  
  13184.      /* Assert np->server_finished_replying == TRUE
  13185.       *     && np->receiving_text == TRUE
  13186.       */ 
  13187.  
  13188.      if (*nnpostfr)
  13189.           sprintf(post_from,"%s@%s (%s)",
  13190.                             zuser, np->client_hostname, nnpostfr);
  13191.      else sprintf(post_from,"%s@%s",
  13192.                             zuser, np->client_hostname);
  13193.  
  13194.      sprintf(np->nntp_command,"Path: %s", post_path);
  13195.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  13196.  
  13197.      sprintf(np->nntp_command,"Newsgroups: %s",post_newsgroups);
  13198.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  13199.  
  13200.      sprintf(np->nntp_command,"Subject: %s",post_subject);
  13201.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  13202.  
  13203.      sprintf(np->nntp_command,"Message-ID: %s", post_message_id);
  13204.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  13205.  
  13206.      sprintf(np->nntp_command,"From: %s", post_from);
  13207.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  13208.  
  13209.      sprintf(np->nntp_command,"Date: %s", datestr);
  13210.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  13211.  
  13212.      /* insert optional headers here if we ever have any */
  13213.  
  13214.      sprintf(np->nntp_command,"Sender: MVS NNTP News Reader <%s@%s>",
  13215.                               NNMVS_NAME, np->client_hostname);
  13216.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  13217.  
  13218.      if (ap) {
  13219.     /*
  13220.      * Uncomment this section when a references field in the
  13221.      * newsarticle struct is added.  Will require total recompilation
  13222.      *
  13223.      * if (ap->references)
  13224.      *  sprintf(np->nntp_command,"References: %s %s",
  13225.      *          ap->references, ap->message_id);
  13226.      * else
  13227.      */
  13228.         sprintf(np->nntp_command,"References: %s",ap->message_id);
  13229.        if (!NNMsockt(np)) break;   /* Send socket command to server */
  13230.      }
  13231.  
  13232.      /* optional headers */
  13233.  
  13234.      if (*nnpostrt) {
  13235.        sprintf(np->nntp_command,"Reply-to: %s", nnpostrt);
  13236.        if (!NNMsockt(np)) break;   /* Send socket command to server */
  13237.      }
  13238.      if (*post_followup_to) {
  13239.        sprintf(np->nntp_command,"Followup-to: %s", post_followup_to);
  13240.        if (!NNMsockt(np)) break;   /* Send socket command to server */
  13241.      }
  13242.  
  13243.      strcpy(np->nntp_command,"");
  13244.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  13245.  
  13246.      while (!feof(efp) && !ferror(efp)) {
  13247.        fgets(postline,sizeof(postline),efp);
  13248.        if (feof(efp)) break;
  13249.        if (ferror(efp)) break;
  13250.        if (*postline && postline[l=strlen(postline)-1] == '\n')
  13251.           postline[l] = '\0';
  13252.        if (postline[0] == '.') strcpy(np->nntp_command,".");
  13253.        else                    strcpy(np->nntp_command,"");
  13254.        strcat(np->nntp_command,postline);
  13255.        if (!NNMsockt(np)) break;   /* Send socket command to server */
  13256.      }
  13257.  
  13258.      strcpy(np->nntp_command,".");
  13259.      if (!NNMsockt(np)) break;   /* Send socket command to server */
  13260.  
  13261.      if (!NNMgsrvl(np,&lp)) break;  /* Get server line */
  13262.      switch (np->nntp_message_num) {
  13263.        case 240: post_error = FALSE;
  13264.                  break;
  13265.        case 441: NNMclrtx(np,NULL);               /* Clear text */
  13266.                  NNMouttx(np,np->server_buf,NULL);/* Output text line */
  13267.                  NNMvtx(np,NULL,NULL);            /* View text */
  13268.  ERR2("Posting failed.  Server %s rejected the post.",np->nnserver);
  13269.                  post_error = TRUE;
  13270.                  break;
  13271.        default:  NNMrperr(np);       /* Report protocol error */
  13272.                  post_error = TRUE;
  13273.                  break;
  13274.      }
  13275.  
  13276.      NNMesrvr(np);                   /* End server read */
  13277.  
  13278.      break;
  13279.  
  13280.    } while(FALSE); /* one-time DO so I can break out of it */
  13281.  
  13282.    if (!post_error) {
  13283.      (void)NNMivput(np,"NNPOSTID ",post_message_id,-1);
  13284.      WARN2("Your article has been posted.  Message ID: %s",
  13285.            post_message_id);
  13286.      break;
  13287.    }
  13288.  
  13289.  }
  13290.  
  13291.  if (!efp) return;
  13292.  
  13293.  if (ferror(efp)) {
  13294.    ERR2("Error trying to read from temp data set: %s", tempdsn);
  13295.  }
  13296.  
  13297.  if (fclose(efp) < 0) {
  13298.    ERR2("Error trying to close temp data set: %s", tempdsn);
  13299.  }
  13300.  
  13301.  if (ap) {
  13302.    if (remove(tempdsn) < 0) {
  13303.      ERR2("Error trying to delete temp data set: %s", tempdsn);
  13304.    }
  13305.  }
  13306.  
  13307.  return; 
  13308. }
  13309.  
  13310. ./   ADD NAME=NNMDSOPT,SSI=01010013
  13311.  
  13312.  /********************************************************************/
  13313.  /*                                                                  */
  13314.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13315.  /*                                                                  */
  13316.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13317.  /* including the implied warranties of merchantability and fitness, */
  13318.  /* are expressly denied.                                            */
  13319.  /*                                                                  */
  13320.  /* Provided this copyright notice is included, this software may    */
  13321.  /* be freely distributed and not offered for sale.                  */
  13322.  /*                                                                  */
  13323.  /* Changes or modifications may be made and used only by the maker  */
  13324.  /* of same, and not further distributed.  Such modifications should */
  13325.  /* be mailed to the author for consideration for addition to the    */
  13326.  /* software and incorporation in subsequent releases.               */
  13327.  /*                                                                  */
  13328.  /********************************************************************/
  13329.  
  13330. #pragma  csect(code,  "NN@DSOPT")
  13331. #pragma  csect(static,"NN$DSOPT")
  13332. #include "nn.h"
  13333.  
  13334. /****** Set options. *************************************************/
  13335.  
  13336. static void
  13337. set_options(np,panelname,which)
  13338. Rstruc nncb       *np;
  13339. char              *panelname;
  13340. enum user_option   which;
  13341. {
  13342.  
  13343.  while (NNMdispl(np,panelname) == 0) {
  13344.    NNMsopt(np,which);               /* Actually set options */
  13345.  }
  13346.  
  13347.  return; 
  13348. }
  13349.  
  13350. /****** Option ... set NNMVS default processing options. *************/
  13351.  
  13352. void
  13353. NNMdsopt(np,option)
  13354. Rstruc nncb *np;
  13355. char        *option;
  13356. {
  13357.  Bool        asked_for;
  13358.  Bool        force_choice;
  13359.  char        nnchoice[9];
  13360.  
  13361.  force_choice = FALSE;
  13362.  
  13363.  do {
  13364.  
  13365.    asked_for = TRUE;
  13366.  
  13367.    if (!force_choice && option && *option) {
  13368.      strncpy(nnchoice,option,sizeof(nnchoice)-1);
  13369.  
  13370.    }
  13371.    else {
  13372.  
  13373.      (void)NNMispf(np,"ADDPOP");
  13374.      if (NNMdispl(np,"NNMPOPT ") > 0) {
  13375.        asked_for = FALSE;
  13376.      }
  13377.      else {
  13378.        (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
  13379.        if (*nnchoice == '?') {
  13380.          ERR1("Invalid choice;\
  13381. Move the cursor to a selection (or type S next to it) and press ENTER."
  13382.              );
  13383.        } 
  13384.      }
  13385.  
  13386.      (void)NNMispf(np,"REMPOP");
  13387.    }
  13388.  
  13389.    if (asked_for) {
  13390.  
  13391.      if      (EQUAL(nnchoice,"1")) {
  13392.        set_options(np,"NNMRFCH ",OPTION_HEADER);
  13393.        break;
  13394.      }
  13395.      else if (EQUAL(nnchoice,"2")) {
  13396.        set_options(np,"NNMOPTS ",OPTION_OTHER);
  13397.        break;
  13398.      }
  13399.      else if (EQUAL(nnchoice,"3")) {
  13400.        set_options(np,"NNMOPTT ",OPTION_VIEW);
  13401.        break;
  13402.      }
  13403.      else {
  13404.        ERR1("Invalid choice;\
  13405. Move the cursor to a selection (or type S next to it) and press ENTER."
  13406.            );
  13407.        force_choice = TRUE;
  13408.        continue;
  13409.      }
  13410.    }
  13411.  
  13412.  } while (asked_for);
  13413.  
  13414.  return; 
  13415.  
  13416. }
  13417.  
  13418. ./   ADD NAME=NNMDUMP,SSI=01010055
  13419.  
  13420.  /********************************************************************/
  13421.  /*                                                                  */
  13422.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13423.  /*                                                                  */
  13424.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13425.  /* including the implied warranties of merchantability and fitness, */
  13426.  /* are expressly denied.                                            */
  13427.  /*                                                                  */
  13428.  /* Provided this copyright notice is included, this software may    */
  13429.  /* be freely distributed and not offered for sale.                  */
  13430.  /*                                                                  */
  13431.  /* Changes or modifications may be made and used only by the maker  */
  13432.  /* of same, and not further distributed.  Such modifications should */
  13433.  /* be mailed to the author for consideration for addition to the    */
  13434.  /* software and incorporation in subsequent releases.               */
  13435.  /*                                                                  */
  13436.  /********************************************************************/
  13437.  
  13438. #pragma  csect(code,  "NN@DUMP ")
  13439. #pragma  csect(static,"NN$DUMP ")
  13440. #include "nn.h"
  13441.  
  13442. /****** Dump some data. **********************************************/
  13443.  
  13444. void
  13445. NNMdump(struct nncb *np, char *label, char *p,int r)
  13446. {
  13447.  int i;
  13448.  
  13449.  if (!np->debug_file) return;
  13450.  
  13451.  if (r == -2) {
  13452.    fprintf(np->debug_file,"%s:  %d\n",label,(int)p);
  13453.    return;
  13454.  }
  13455.  
  13456.  if (r == -1) r = strlen(p);
  13457.  
  13458.  fprintf(np->debug_file,"%s:   (%d characters)\n",label,r);
  13459.  for (i=0;i<77;i++) fprintf(np->debug_file,"-");
  13460.  fprintf(np->debug_file,"\n");
  13461.  for (i=0;i<r;i++) {
  13462.    char c = *(p+i);
  13463.    if (isprint(c))  fprintf(np->debug_file,"%c",c);
  13464.    else             fprintf(np->debug_file,"<0x%2.2x>",c);
  13465.  }
  13466.  fprintf(np->debug_file,"\n");
  13467.  for (i=0;i<77;i++) fprintf(np->debug_file,"-");
  13468.  fprintf(np->debug_file,"\n");
  13469.  
  13470.  fflush(np->debug_file);
  13471.  
  13472.  return; 
  13473.  
  13474. }
  13475.  
  13476. ./   ADD NAME=NNMESRVR,SSI=01020033
  13477.  
  13478.  /********************************************************************/
  13479.  /*                                                                  */
  13480.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13481.  /*                                                                  */
  13482.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13483.  /* including the implied warranties of merchantability and fitness, */
  13484.  /* are expressly denied.                                            */
  13485.  /*                                                                  */
  13486.  /* Provided this copyright notice is included, this software may    */
  13487.  /* be freely distributed and not offered for sale.                  */
  13488.  /*                                                                  */
  13489.  /* Changes or modifications may be made and used only by the maker  */
  13490.  /* of same, and not further distributed.  Such modifications should */
  13491.  /* be mailed to the author for consideration for addition to the    */
  13492.  /* software and incorporation in subsequent releases.               */
  13493.  /*                                                                  */
  13494.  /********************************************************************/
  13495.  
  13496. #pragma  csect(code,  "NN@ESRVR")
  13497. #pragma  csect(static,"NN$ESRVR")
  13498. #include "nn.h"
  13499.  
  13500. /****** End server read. *********************************************/
  13501.  
  13502. void
  13503. NNMesrvr(np)
  13504. Rstruc nncb  *np;
  13505. {
  13506.  char       *lp;
  13507.  Bool        found_more_server_data = FALSE;
  13508.  Bool        save_dont_reissue_socket_command;
  13509.  
  13510.  NNMclrtx(np,NULL);                    /* Clear text */
  13511.  
  13512.  save_dont_reissue_socket_command = np->dont_reissue_socket_command;
  13513.  np->dont_reissue_socket_command = TRUE;
  13514.  
  13515.  do {
  13516.  
  13517.    if (NNMgsrvl(np,&lp)) {             /* Get server line */
  13518.      if (lp) {
  13519.        found_more_server_data = TRUE;
  13520.        (void)NNMouttx(np,lp,NULL);     /* Output text line */
  13521.      }
  13522.    }
  13523.  
  13524.  } while (lp);
  13525.  
  13526.  if (found_more_server_data) {
  13527.    ERR1( 
  13528. "More data was returned by the news server than the client expected."
  13529.        );
  13530.    NNMvtx(np,NULL,NULL);               /* View text */
  13531.  }
  13532.  
  13533.  np->dont_reissue_socket_command = save_dont_reissue_socket_command;
  13534.  
  13535.  return; 
  13536. }
  13537.  
  13538. ./   ADD NAME=NNMESTNG,SSI=01000022
  13539.  
  13540.  /********************************************************************/
  13541.  /*                                                                  */
  13542.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13543.  /*                                                                  */
  13544.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13545.  /* including the implied warranties of merchantability and fitness, */
  13546.  /* are expressly denied.                                            */
  13547.  /*                                                                  */
  13548.  /* Provided this copyright notice is included, this software may    */
  13549.  /* be freely distributed and not offered for sale.                  */
  13550.  /*                                                                  */
  13551.  /* Changes or modifications may be made and used only by the maker  */
  13552.  /* of same, and not further distributed.  Such modifications should */
  13553.  /* be mailed to the author for consideration for addition to the    */
  13554.  /* software and incorporation in subsequent releases.               */
  13555.  /*                                                                  */
  13556.  /********************************************************************/
  13557.  
  13558. #pragma  csect(code,  "NN@ESTNG")
  13559. #pragma  csect(static,"NN$ESTNG")
  13560. #include "nn.h"
  13561.  
  13562. /****** Establish newsgroup. *****************************************/
  13563.  
  13564. Bool
  13565. NNMestng(np,group)
  13566. Rstruc nncb        *np;
  13567. char               *group;
  13568. {
  13569.  char              *lp;
  13570.  Bool               null_group_passed = FALSE;
  13571.  
  13572.  /* A null group means reissue the server command to select the
  13573.     current newsgroup if it is necessary. */
  13574.  
  13575.  if (!group) {
  13576.    null_group_passed = TRUE;
  13577.    if (!np->current_newsgroup) {
  13578.      fprintf(stderr,"NNMestng: no current newsgroup\n");
  13579.      return FALSE;
  13580.    }
  13581.    if (np->newsgroup_selected) return TRUE;
  13582.    group = np->current_newsgroup->name;
  13583.  }
  13584.  
  13585.  np->newsgroup_not_found = FALSE;
  13586.  
  13587.  /* Send "GROUP xxxx" to news server. */
  13588.  
  13589.  strcpy(np->nntp_command,"GROUP ");
  13590.  strcat(np->nntp_command,group);
  13591.  if (!NNMsockt(np)) return FALSE;    /* Send socket command to server */
  13592.  
  13593.    /* Receive response.  Should be one of:
  13594.     *   211 n f l s group selected
  13595.     *   411 no such news group
  13596.     */
  13597.  
  13598.  if (!NNMgsrvl(np,&lp)) return FALSE;  /* Get server line */
  13599.  switch (np->nntp_message_num) {
  13600.    case 211:                           /* n f l s group selected */
  13601.              break;
  13602.    case 411:                               /* no such news group */
  13603.              fprintf(stderr,"%s: no such newsgroup\n",group);
  13604.              ERR3("No such newsgroup.  %s is unknown to server %s.",
  13605.                   group, np->nnserver);
  13606.              np->newsgroup_not_found = TRUE;
  13607.              return FALSE;
  13608.    default:
  13609.              NNMrperr(np);        /* Report protocol error */
  13610.              return FALSE;
  13611.  }
  13612.  
  13613.  np->newsgroup_selected = TRUE;
  13614.  
  13615.  return TRUE;
  13616.  
  13617. }
  13618.  
  13619. ./   ADD NAME=NNMFREEM,SSI=01010050
  13620.  
  13621.  /********************************************************************/
  13622.  /*                                                                  */
  13623.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13624.  /*                                                                  */
  13625.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13626.  /* including the implied warranties of merchantability and fitness, */
  13627.  /* are expressly denied.                                            */
  13628.  /*                                                                  */
  13629.  /* Provided this copyright notice is included, this software may    */
  13630.  /* be freely distributed and not offered for sale.                  */
  13631.  /*                                                                  */
  13632.  /* Changes or modifications may be made and used only by the maker  */
  13633.  /* of same, and not further distributed.  Such modifications should */
  13634.  /* be mailed to the author for consideration for addition to the    */
  13635.  /* software and incorporation in subsequent releases.               */
  13636.  /*                                                                  */
  13637.  /********************************************************************/
  13638.  
  13639. #pragma  csect(code,  "NN@FREEM")
  13640. #pragma  csect(static,"NN$FREEM")
  13641. #include "nn.h"
  13642.  
  13643. /****** Free memory. *************************************************/
  13644.  
  13645. void
  13646. NNMfreem(np,stuff,whatfor)
  13647. Rstruc nncb    *np;
  13648. char           *stuff;
  13649. char           *whatfor;
  13650. {
  13651.  
  13652.  free(stuff);
  13653.  
  13654.  if (np->debug_file) {
  13655.    fprintf(np->debug_file,"NNMfreem: freed memory for %s\n", whatfor);
  13656.  }
  13657.  return; 
  13658.  
  13659. }
  13660.  
  13661. ./   ADD NAME=NNMGETDS,SSI=011A0058
  13662.  
  13663.  /********************************************************************/
  13664.  /*                                                                  */
  13665.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  13666.  /*                                                                  */
  13667.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  13668.  /*                                                                  */
  13669.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  13670.  /* including the implied warranties of merchantability and fitness, */
  13671.  /* are expressly denied.                                            */
  13672.  /*                                                                  */
  13673.  /* Provided this copyright notice is included, this software may    */
  13674.  /* be freely distributed and not offered for sale.                  */
  13675.  /*                                                                  */
  13676.  /* Changes or modifications may be made and used only by the maker  */
  13677.  /* of same, and not further distributed.  Such modifications should */
  13678.  /* be mailed to the author for consideration for addition to the    */
  13679.  /* software and incorporation in subsequent releases.               */
  13680.  /*                                                                  */
  13681.  /********************************************************************/
  13682.  
  13683. #pragma  csect(code,  "NN@GETDS")
  13684. #pragma  csect(static,"NN$GETDS")
  13685. #include "nn.h"
  13686.  
  13687. #define DUMMY_FILE_POINTER_FOR_PDS  (FILE *)(-1)
  13688.  
  13689. struct sysout    {
  13690.                   int        copies;
  13691.                   char       class [2];
  13692.                   char       dest  [9];
  13693.                   char       forms [5];
  13694.                   char       ucs   [5];
  13695.                  };
  13696.  
  13697. /****** Function to close sequential data set after extraction. ******/
  13698.  
  13699. static void
  13700. close_seq(np,ep,xfp,final)
  13701. Rstruc nncb         *np;
  13702. Rstruc extraction   *ep;
  13703. FILE                *xfp;
  13704. Fool                 final;
  13705. {
  13706.  
  13707.  if (fclose(xfp) < 0) {
  13708.    /* perror(ep->dsname); */
  13709.    ERR2("An error occurred closing %s.", ep->dsname);
  13710.    np->extract_close_error = TRUE;
  13711.  }
  13712.  
  13713. }
  13714.  
  13715. /****** Function to close partitioned data set after extraction. *****/
  13716.  
  13717. static void
  13718. close_pds(np,ep,xfp,final)
  13719. Rstruc nncb         *np;
  13720. Rstruc extraction   *ep;
  13721. FILE                *xfp;
  13722. Fool                 final;
  13723. {
  13724.  
  13725.  if (final) {
  13726.    (void)NNMunalc(ep->ddname);     /* Unallocate the PDS */
  13727.  }
  13728.  else {
  13729.    if (fclose(xfp) < 0) {
  13730.      /* perror(ep->dsname); */
  13731.      ERR2("An error occurred closing %s.", ep->dsname);
  13732.      np->extract_close_error = TRUE;
  13733.    }
  13734.  }
  13735.  
  13736. }
  13737.  
  13738. /****** Function to close SYSOUT print file after printing. **********/
  13739.  
  13740. static void
  13741. close_jes(np,ep,xfp,final)
  13742. Rstruc nncb         *np;
  13743. Rstruc extraction   *ep;
  13744. FILE                *xfp;
  13745. Fool                 final;
  13746. {
  13747.  
  13748.  if (fclose(xfp) < 0) {
  13749.    /* perror(ep->dsname); */
  13750.    ERR2("An error occurred closing %s.", ep->dsname);
  13751.    np->extract_close_error = TRUE;
  13752.  }
  13753.  if (final) {
  13754.    (void)NNMunalc(ep->ddname);     /* Unallocate the SYSOUT file */
  13755.  }
  13756.  
  13757. }
  13758.  
  13759. /****** Allocate SYSOUT file. ****************************************/
  13760.  
  13761. static Bool
  13762. allocate_sysout(ep,sp)
  13763. Rstruc extraction   *ep;
  13764. Rstruc sysout       *sp;
  13765. {
  13766.  int          i;
  13767.  int          rc;
  13768.  char        *cp;
  13769.  __S99parms   stuff99;   /* The manual has it wrong.  No "struct". */
  13770.  TEXTUNIT    *tu [ 7];
  13771.  TEXTUNIT     tu_sysout;
  13772.  TEXTUNIT     tu_copies;
  13773.  TEXTUNIT     tu_dest;
  13774.  TEXTUNIT     tu_forms;
  13775.  TEXTUNIT     tu_ucs;
  13776.  TEXTUNIT     tu_rtddn;
  13777.  
  13778.  memset((char *)&stuff99,0,sizeof(__S99parms));
  13779.  
  13780.  stuff99.__S99RBLN   = 20;
  13781.  stuff99.__S99VERB   = S99VRBAL;
  13782.  stuff99.__S99FLAG1  = S99NOCNV << 8;
  13783.  stuff99.__S99ERROR  = 0;
  13784.  stuff99.__S99INFO   = 0;
  13785.  stuff99.__S99TXTPP  = tu;
  13786.  stuff99.__S99FLAG2  = 0;
  13787.  
  13788.  i = 0;
  13789.  
  13790.  tu[i++] = &tu_sysout;
  13791.  
  13792.  tu_sysout.key        = DALSYSOU;
  13793.  tu_sysout.num        = 1;
  13794.  tu_sysout.ent.len    = 1;
  13795.  tu_sysout.ent.prm[0] = toupper(sp->class[0]);
  13796.  
  13797.  tu[i++] = &tu_copies;
  13798.  
  13799.  tu_copies.key        = DALCOPYS;
  13800.  tu_copies.num        = 1;
  13801.  tu_copies.ent.len    = 1;
  13802.  tu_copies.ent.prm[0] = (unsigned char)sp->copies;
  13803.  
  13804.  if (sp->dest[0] > ' ') {
  13805.  
  13806.   tu[i++] = &tu_dest;
  13807.  
  13808.   tu_dest.key          = DALSUSER;
  13809.   tu_dest.num          = 1;
  13810.   copy_uppercase_and_strip_trailing(tu_dest.ent.prm,sp->dest,cp);
  13811.   tu_dest.ent.len      = cp - tu_dest.ent.prm;
  13812.  
  13813.  }
  13814.  
  13815.  if (sp->forms[0] > ' ') {
  13816.  
  13817.   tu[i++] = &tu_forms;
  13818.  
  13819.   tu_forms.key         = DALSFMNO;
  13820.   tu_forms.num         = 1;
  13821.   copy_uppercase_and_strip_trailing(tu_forms.ent.prm,sp->forms,cp);
  13822.   tu_forms.ent.len     = cp - tu_forms.ent.prm;
  13823.  
  13824.  }
  13825.  
  13826.  if (sp->ucs[0] > ' ') {
  13827.  
  13828.   tu[i++] = &tu_ucs;
  13829.  
  13830.   tu_ucs.key           = DALUCS;
  13831.   tu_ucs.num           = 1;
  13832.   copy_uppercase_and_strip_trailing(tu_ucs.ent.prm,sp->ucs,cp);
  13833.   tu_ucs.ent.len       = cp - tu_ucs.ent.prm;
  13834.  
  13835.  }
  13836.  
  13837.  tu[i++] = &tu_rtddn;
  13838.  
  13839.  tu_rtddn.key         = DALRTDDN;
  13840.  tu_rtddn.num         = 1;
  13841.  tu_rtddn.ent.len     = 8;
  13842.  memset(tu_rtddn.ent.prm,' ',8);
  13843.  
  13844.  tu[i] = (void *)0x80000000;
  13845.  
  13846.  rc = svc99(&stuff99);
  13847.  
  13848.  if (rc == 0) {
  13849.    memcpy(ep->ddname,(char *)tu_rtddn.ent.prm,8);
  13850.    ep->ddname[8] = ' ';
  13851.    *(strchr(ep->ddname,' ')) = '\0';
  13852.    return TRUE;
  13853.  }
  13854.  else {
  13855.    NNMdfail(rc,&stuff99);
  13856.    return FALSE;
  13857.  }
  13858. }
  13859.  
  13860. /****** Prompt user for the name of a data set to extract into. ******/
  13861.  
  13862. FILE *
  13863. NNMgetds(np,ep)
  13864. Rstruc nncb         *np;
  13865. Rstruc extraction   *ep;
  13866. {
  13867.  FILE               *xfp;
  13868.  char               *panel_to_display;
  13869.  Bool                asked_for;
  13870.  struct sysout       sys;
  13871.  char                nnexdsn[65];    /* data set name for extraction */
  13872.  char                nnexapp [4];    /* YES or NO for append mode    */
  13873.  char                nnextab [4];    /* YES or NO for tab expansion  */
  13874.  char                nnexblk [4];    /* YES or NO for blank after sep*/
  13875.  char                nnexspa [4];    /* YES or NO for page ejects    */
  13876.  char                nnexsep[81];    /* Separator line (optional)    */
  13877.  char                nnexan1[16];    /* From article number          */
  13878.  char                nnexan2[16];    /* To   article number          */
  13879.  char                nnexpmp [9];    /* PDS member name prefix       */
  13880.  char                nnexscl [2];    /* Print SYSOUT class name      */
  13881.  char                nnexsco [4];    /* Print SYSOUT copies number   */
  13882.  char                nnexsde [9];    /* Print SYSOUT destination     */
  13883.  char                nnexsfo [5];    /* Print SYSOUT forms           */
  13884.  char                nnexsuc [5];    /* Print SYSOUT UCS             */
  13885.  char                quoted_dsname [67];
  13886.  
  13887.  /* Display panel asking for data set name into which to extract. */
  13888.  
  13889.  xfp = NULL;
  13890.  asked_for = TRUE;
  13891.  
  13892.  (void)NNMispf(np,"ADDPOP");
  13893.  
  13894.  if (ep->mode == JES) {
  13895.    (void)NNMivput(np,"NNWHICH ",ep->panelname,-1);
  13896.    (void)NNMivput(np,"NNALLPR ",
  13897. #ifdef FULLSYSOUT
  13898.                      "Y",
  13899. #else
  13900.                      "",
  13901. #endif
  13902.                      -1);
  13903.    panel_to_display = "NNMPPRT ";
  13904.  }
  13905.  else panel_to_display = ep->panelname;
  13906.  
  13907.  while (!xfp) {
  13908.  
  13909.    /* Keep asking for a dsname until one works or END pressed. */
  13910.  
  13911.    if (NNMdispl(np,panel_to_display) > 0) {
  13912.      asked_for = FALSE;
  13913.      xfp = NULL;
  13914.      break;
  13915.    }
  13916.  
  13917.    if (ep->mode == JES) {
  13918.      (void)NNMivget(np,"NNEXSCL ",nnexscl,sizeof(nnexscl));
  13919.      (void)NNMivget(np,"NNEXSCO ",nnexsco,sizeof(nnexsco));
  13920. #ifdef FULLSYSOUT
  13921.      (void)NNMivget(np,"NNEXSDE ",nnexsde,sizeof(nnexsde));
  13922.      (void)NNMivget(np,"NNEXSFO ",nnexsfo,sizeof(nnexsfo));
  13923.      (void)NNMivget(np,"NNEXSUC ",nnexsuc,sizeof(nnexsuc));
  13924. #else
  13925.      *nnexsde = '\0';
  13926.      *nnexsfo = '\0';
  13927.      *nnexsuc = '\0';
  13928. #endif
  13929.      (void)NNMivget(np,"NNEXAN1 ",nnexan1,sizeof(nnexan1));
  13930.      (void)NNMivget(np,"NNEXAN2 ",nnexan2,sizeof(nnexan2));
  13931.      (void)NNMivget(np,"NNEXSPA ",nnexspa,sizeof(nnexspa));
  13932.      (void)NNMivget(np,"NNEXBLK ",nnexblk,sizeof(nnexblk));
  13933.      (void)NNMivget(np,"NNEXSEP ",nnexsep,sizeof(nnexsep));
  13934.    }
  13935.    else {
  13936.      (void)NNMivget(np,"NNEXDSN ",nnexdsn,sizeof(nnexdsn));
  13937.      (void)NNMivget(np,"NNEXTAB ",nnextab,sizeof(nnextab));
  13938.      (void)NNMivget(np,"NNEXAN1 ",nnexan1,sizeof(nnexan1));
  13939.      (void)NNMivget(np,"NNEXAN2 ",nnexan2,sizeof(nnexan2));
  13940.      if (ep->mode == PDS) {
  13941.        (void)NNMivget(np,"NNEXPMP ",nnexpmp,sizeof(nnexpmp));
  13942.      }
  13943.      else {
  13944.        (void)NNMivget(np,"NNEXAPP ",nnexapp,sizeof(nnexapp));
  13945.        (void)NNMivget(np,"NNEXBLK ",nnexblk,sizeof(nnexblk));
  13946.        (void)NNMivget(np,"NNEXSEP ",nnexsep,sizeof(nnexsep));
  13947.      }
  13948.    }
  13949.  
  13950.    if (ep->mode == PDS) {
  13951.  
  13952.      ep->closer = close_pds;
  13953.      ep->appending = FALSE;
  13954.      ep->blanking  = FALSE;
  13955.      strcpy(ep->separator,"");
  13956.      strcpy(ep->ddname,"");
  13957.      strcpy(ep->member_prefix,nnexpmp);
  13958.  
  13959.      /* Note: panel forces fully-qualified name to pass to allocate */
  13960.  
  13961.      if (nnexdsn[0] != '\'') {
  13962.        strcpy(quoted_dsname,"'");
  13963.        strcat(quoted_dsname,nnexdsn);
  13964.        strcat(quoted_dsname,"'");
  13965.      }
  13966.      else strcpy(quoted_dsname,nnexdsn);
  13967.  
  13968.      /* Check if PDS already exists. */
  13969.  
  13970.      if (np->warn_overwrite) {
  13971.        if (TEST_IF_FILE_EXISTS(xfp,quoted_dsname)) {
  13972.          CLEANUP_IF_FILE_EXISTS(xfp);
  13973.          xfp = NULL;
  13974.          if (NNMdispl(np,"NNMPEXPW") > 0) {
  13975.            WARN1("Operation cancelled, because you pressed END.");
  13976.            break;
  13977.          }
  13978.        } 
  13979.      }
  13980.  
  13981.      if (!NNMalloc(nnexdsn,ep->ddname,PDS,ep->article_count)) {
  13982.        ERR2("Allocation failed for data set %s.", nnexdsn);
  13983.        xfp = NULL;
  13984.        continue;
  13985.      }
  13986.      strcpy(ep->dsname,    nnexdsn);
  13987.      ep->tab_expanding = (nnextab[0] == 'Y');
  13988.    }
  13989.    else if (ep->mode == JES) {
  13990.      ep->closer = close_jes;
  13991.      strcpy(ep->separator, nnexsep);
  13992.      sprintf(ep->dsname,"SYSOUT class %s",nnexscl);
  13993.      memset(&sys,0,sizeof(sys));
  13994.      strcpy(sys.class, nnexscl);
  13995.      sys.copies = atoi(nnexsco);
  13996.      if (sys.copies < 1) sys.copies = 1;
  13997.      strcpy(sys.dest,  nnexsde);
  13998.      strcpy(sys.forms, nnexsfo);
  13999.      strcpy(sys.ucs,   nnexsuc);
  14000.      ep->ejecting      = (nnexspa[0] == 'Y');
  14001.      ep->appending     = FALSE;
  14002.      ep->blanking      = (nnexblk[0] == 'Y');
  14003.      ep->tab_expanding = TRUE;
  14004.    }
  14005.    else {
  14006.      ep->closer = close_seq;
  14007.      strcpy(ep->separator, nnexsep);
  14008.      strcpy(ep->dsname,    nnexdsn);
  14009.      ep->appending      = (nnexapp[0] == 'Y');
  14010.      ep->blanking       = (nnexblk[0] == 'Y');
  14011.      ep->tab_expanding  = (nnextab[0] == 'Y');
  14012.    }
  14013.  
  14014.    if (*nnexan1) ep->from_article_number = atoi(nnexan1);
  14015.    else          ep->from_article_number = 0;
  14016.    if (*nnexan2) ep->to_article_number   = atoi(nnexan2);
  14017.    else          ep->to_article_number   = INT_MAX;
  14018.  
  14019.    /* check if the dataset already exists */
  14020.    /* (Wonder if this will compile.  Have fun, "cc"...) */
  14021.  
  14022.    if (ep->mode != JES) {
  14023.      if (ep->appending ? np->warn_append : np->warn_overwrite) {
  14024.        if (TEST_IF_FILE_EXISTS(xfp,nnexdsn)) {
  14025.          CLEANUP_IF_FILE_EXISTS(xfp);
  14026.          xfp = NULL;
  14027.          if (NNMdispl(np,"NNMPEXOW") > 0) {
  14028.            WARN1("Operation cancelled, because you pressed END.");
  14029.            break;
  14030.          }
  14031.        } 
  14032.      }
  14033.    }
  14034.  
  14035.    if (ep->mode == JES) {
  14036.      if (allocate_sysout(ep,&sys)) {
  14037.        sprintf(nnexdsn,"dd:%s",ep->ddname);
  14038.      }
  14039.      else *nnexdsn = '\0';
  14040.    }
  14041.  
  14042.    if (ep->mode == PDS) {
  14043.      xfp = DUMMY_FILE_POINTER_FOR_PDS;
  14044.      break;
  14045.    }
  14046.  
  14047.    if (*nnexdsn) {
  14048.  
  14049.      if (ep->mode == JES) {
  14050.        xfp = OPEN_SYSOUT_FILE(nnexdsn);
  14051.      }
  14052.      else {
  14053.        xfp = OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(nnexdsn,ep->appending);
  14054.      }
  14055.  
  14056.      if (!xfp) {
  14057.        fprintf(stderr,"Open failure: errno=%d\n",errno);
  14058.        perror(nnexdsn);
  14059.        ERR2("Cannot open %s.", ep->dsname);
  14060.      }
  14061.    }
  14062.  }
  14063.  
  14064.  (void)NNMispf(np,"REMPOP");
  14065.  
  14066.  return xfp;
  14067.  
  14068. }
  14069.  
  14070. ./   ADD NAME=NNMGETM,SSI=01000041
  14071.  
  14072.  /********************************************************************/
  14073.  /*                                                                  */
  14074.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  14075.  /*                                                                  */
  14076.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  14077.  /* including the implied warranties of merchantability and fitness, */
  14078.  /* are expressly denied.                                            */
  14079.  /*                                                                  */
  14080.  /* Provided this copyright notice is included, this software may    */
  14081.  /* be freely distributed and not offered for sale.                  */
  14082.  /*                                                                  */
  14083.  /* Changes or modifications may be made and used only by the maker  */
  14084.  /* of same, and not further distributed.  Such modifications should */
  14085.  /* be mailed to the author for consideration for addition to the    */
  14086.  /* software and incorporation in subsequent releases.               */
  14087.  /*                                                                  */
  14088.  /********************************************************************/
  14089.  
  14090. #pragma  csect(code,  "NN@GETM ")
  14091. #pragma  csect(static,"NN$GETM ")
  14092. #include "nn.h"
  14093.  
  14094. /****** Get memory. **************************************************/
  14095.  
  14096. void
  14097. NNMgetm(np,pointer,howmuch,whatfor)
  14098. Rstruc nncb    *np;
  14099. char          **pointer;
  14100. int             howmuch;
  14101. char           *whatfor;
  14102. {
  14103.  
  14104.  *pointer = (char *)malloc(howmuch);
  14105.  
  14106.  if (!*pointer) {
  14107.    fprintf(stderr,"NNMVS: Cannot obtain %d bytes of memory for %s\n",
  14108.                   howmuch,whatfor);
  14109.  }
  14110.  else if (np->debug_file) {
  14111.    fprintf(np->debug_file,"NNMgetm: got %d bytes of memory for %s\n",
  14112.                            howmuch,whatfor);
  14113.  }
  14114.  return; 
  14115.  
  14116. }
  14117.  
  14118. ./   ADD NAME=NNMGSRVL,SSI=011D0050
  14119.  
  14120.  /********************************************************************/
  14121.  /*                                                                  */
  14122.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  14123.  /*                                                                  */
  14124.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  14125.  /* including the implied warranties of merchantability and fitness, */
  14126.  /* are expressly denied.                                            */
  14127.  /*                                                                  */
  14128.  /* Provided this copyright notice is included, this software may    */
  14129.  /* be freely distributed and not offered for sale.                  */
  14130.  /*                                                                  */
  14131.  /* Changes or modifications may be made and used only by the maker  */
  14132.  /* of same, and not further distributed.  Such modifications should */
  14133.  /* be mailed to the author for consideration for addition to the    */
  14134.  /* software and incorporation in subsequent releases.               */
  14135.  /*                                                                  */
  14136.  /********************************************************************/
  14137.  
  14138. #pragma  csect(code,  "NN@GSRVL")
  14139. #pragma  csect(static,"NN$GSRVL")
  14140. #include "nn.h"
  14141.  
  14142. #define  GOT_NOTHING        0
  14143. #define  GOT_SOMETHING      1
  14144. #define  GOT_DISCONNECT     2
  14145. #define  GOT_NOTAUTHORIZED  3
  14146.  
  14147. /* separate this and call it NNMGAUTH eventually */
  14148.  
  14149. /****** Send authorization to news server. ***************************/
  14150.  
  14151. static Bool
  14152. NNMgauth(np)
  14153. Rstruc nncb *np;
  14154. {
  14155.  
  14156.  char              *lp;
  14157.  FILE              *fp;
  14158.  int                display_rc;
  14159.  Bool               auth_error;
  14160.  Bool               connection_probably_closed;
  14161.  char               nnauser   [65];
  14162.  char               nnapass   [65];
  14163.  
  14164.  /* NNTP numbers must be the following as defined in C News source:
  14165.   *
  14166.   * OK_AUTHSYS    280  authorization system OK
  14167.   * OK_AUTH       281  authorization OK
  14168.   * NEED_AUTHINFO 380  authorization is required
  14169.   * NEED_AUTHDATA 381  <type> authorization data required (e.g. PASS)
  14170.   * ERR_NOAUTH    480  authorization required for command
  14171.   * ERR_AUTHSYS   481  authorization system invalid
  14172.   * ERR_AUTHREJ   482  authorization data rejected
  14173.   * ERR_CMDSYN    501  command syntax error
  14174.   * ERR_COMMAND   500  command not implemented
  14175.   * ERR_ACCESS    502  access to server denied
  14176.   * ERR_AUTHBAD   580  authorization failed
  14177.   *
  14178.   * Me:     AUTHINFO USER username
  14179.   * Server: 381 PASS required
  14180.   *     or: 482 Authorization already completed
  14181.   *     or: 500 Command not recognized
  14182.   *
  14183.   * If 482, server does not accept our attempt to gain authorization.
  14184.   *
  14185.   * If 500, authorization is not needed or the server has never
  14186.   * heard of authorization.  Either way, we proceed as "authorized".
  14187.   *
  14188.   * If 381 ...
  14189.   *
  14190.   * Me:     AUTHINFO PASS password
  14191.   * Server: 281 Authorization OK
  14192.   *     or: 482 authorization data rejected
  14193.   *     or: 502 access to server denied
  14194.   *     or: 580 authorization failed
  14195.   *
  14196.   * If 502, the server has disconnected me and I should return FALSE.
  14197.   * Otherwise, everything is OK, and I should return TRUE.
  14198.   *
  14199.   */
  14200.  
  14201.  lp = "None - local system error accessing authorization file";
  14202.  
  14203.  auth_error = FALSE;
  14204.  connection_probably_closed = FALSE;
  14205.  *nnauser   = '\0';
  14206.  *nnapass   = '\0';
  14207.  
  14208.  (void)NNMivget(np,"NNAUSER ",nnauser,sizeof(nnauser));
  14209.  if (!*nnauser) {
  14210.    (void)NNMivget(np,"ZUSER ",nnauser,sizeof(nnauser));
  14211.    lowercase_in_place(nnauser);
  14212.    (void)NNMivput(np,"NNAUSER ",nnauser,-1);
  14213.  }
  14214.  
  14215.  /* Read user and pass from terminal */
  14216.  /* temporary. change to panel */
  14217.  
  14218.  (void)NNMivput(np,"NNSERVER ",np->nnserver,-1);
  14219.  (void)NNMispf(np,"ADDPOP");
  14220.  (void)NNMdispl(np,"NNMPGAUT");
  14221.  display_rc = np->ispfrc;
  14222.  (void)NNMispf(np,"REMPOP");
  14223.  if (display_rc != 0) return FALSE;
  14224.  (void)NNMivget(np,"NNAUSER ",nnauser,sizeof(nnauser));
  14225.  (void)NNMivget(np,"NNAPASS ",nnapass,sizeof(nnapass));
  14226.  sprintf(np->nntp_command,"AUTHINFO USER %s", nnauser);
  14227.  if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
  14228.  if (!NNMgsrvl(np,&lp)) return FALSE;  /* Get server line */
  14229.  switch (np->nntp_message_num) {
  14230.    case 381: /* PASS required */
  14231.              break;
  14232.    default:  NNMrperr(np);       /* Report protocol error */
  14233.              auth_error = TRUE;
  14234.              break;
  14235.  }
  14236.  
  14237.  if (!auth_error) {
  14238.    sprintf(np->nntp_command,"AUTHINFO PASS %s", nnapass);
  14239.    if (!NNMsockt(np)) return FALSE; /* Send socket command to server */
  14240.    if (!NNMgsrvl(np,&lp)) return FALSE;  /* Get server line */
  14241.    switch (np->nntp_message_num) {
  14242.      case 281: /* authorization OK */
  14243.                return TRUE;
  14244.      case 502: /* access to server denied */
  14245.                /* Also, we have been disconnected at this point. */
  14246.                connection_probably_closed = TRUE;
  14247.                auth_error = TRUE;
  14248.                break;
  14249.      default:  NNMrperr(np);       /* Report protocol error */
  14250.                auth_error = TRUE;
  14251.                break;
  14252.    }
  14253.  }
  14254.  
  14255.  NNMesrvr(np);                   /* End server read */
  14256.  
  14257.  if (auth_error) {
  14258.  
  14259.    if (connection_probably_closed) {
  14260.      ERR2("Authorization failed;\
  14261. The NNTP server at %s refuses to authorize you.  \
  14262. Some news operations may fail.",\
  14263.           np->nnserver);
  14264.      /* np->connection_broken = TRUE; */
  14265.      /* NNMdisc(np); */               /* Complete disconnection */
  14266.      return FALSE;
  14267.    }
  14268.    else {
  14269.      if (np->batch_mode) {
  14270.        fprintf(stderr,
  14271.         "NNMVS could not obtain authorization from the NNTP server.\n");
  14272.        fprintf(stderr,
  14273.         "NNMVS will proceed, but some news operations may fail.\n");
  14274.        fprintf(stderr,
  14275.         "The response from server %s was:\n\n%s\n\n", np->nnserver,lp);
  14276.        return FALSE;
  14277.      }
  14278.      else {
  14279.        NNMivput(np,"NNSRVRSP ",lp,          -1);
  14280.        (void)NNMispf(np,"ADDPOP ");
  14281.        (void)NNMispf(np,"DISPLAY PANEL(NNMPAUTH)");
  14282.        display_rc = np->ispfrc;
  14283.        (void)NNMispf(np,"REMPOP ");
  14284.        if (display_rc == 0) return FALSE;
  14285.        else {
  14286.          /* NNMdisc(np); */
  14287.          return FALSE;
  14288.        } 
  14289.      }
  14290.    }
  14291.  }
  14292.  
  14293.  return TRUE;
  14294.  
  14295. }
  14296.  
  14297. /****** Input one character from the server. *************************/
  14298.  
  14299. static int
  14300. socket_getchar(np)
  14301. Rstruc nncb  *np;
  14302. {
  14303.  int         readrc;
  14304.  
  14305.  if (np->g_buf_index == -1 ||
  14306.      np->g_buf_index >= np->g_bytes_returned - 1) {
  14307.    np->g_buf_index = -1;
  14308.    if (np->dont_read) return(SOCKET_NO_MORE);
  14309.    else {
  14310.      TCP_DEBUG_ON;
  14311.      readrc = read(np->socknum, np->g_buf, READ_BYTES);
  14312.      TCP_DEBUG_OFF;
  14313.      if (readrc == -1) {
  14314.        np->connection_broken = TRUE;
  14315.        return SOCKET_GETCHAR_ERROR;
  14316.      }
  14317.      else if (readrc == 0) {
  14318.        np->connection_broken = TRUE;
  14319.        return SOCKET_READ_NOTHING;
  14320.      }
  14321.      else {
  14322. #ifdef MVS
  14323.        ASCII_TO_EBCDIC(np->g_buf,readrc);
  14324. #endif
  14325.        np->g_bytes_returned = readrc;
  14326.        if (np->debug_file) {
  14327.          NNMdump(np,"Data read from server",np->g_buf,readrc);
  14328.        } 
  14329.      }
  14330.    }
  14331.  }
  14332.  return np->g_buf[++np->g_buf_index];
  14333. }
  14334.  
  14335. /****** Input one data line at a time from the server. ***************/
  14336.  
  14337. static enum socket_retval
  14338. socket_from_server(np)
  14339. Rstruc nncb *np;
  14340. {
  14341.  char       *s_buf;
  14342.  int         s_bytes;
  14343.  int         s_buf_index;
  14344.  int         character;
  14345.  int         previous_character;
  14346.  
  14347.  s_buf   = np->server_buf;
  14348.  s_bytes = SERVER_BUF_MSGSIZE;
  14349.  
  14350.  /* Get characters from the server until CRLF is reached. */
  14351.  
  14352.  s_buf_index = 0;
  14353.  previous_character = -1;
  14354.  for (;;) {
  14355.    character = socket_getchar(np);
  14356.    if (character == LINE_FEED && previous_character == CARRIAGE_RETURN)
  14357.       break;
  14358.    if (character == SOCKET_GETCHAR_ERROR)  return(SERVER_READ_ERROR);
  14359.    if (character == SOCKET_NO_MORE)        return(SERVER_NO_MORE);
  14360.    if (character == SOCKET_READ_NOTHING)   return(SERVER_READ_ERROR);
  14361.    previous_character = character;
  14362.    if (s_buf_index >= s_bytes) {
  14363.      fprintf(stderr,"Error: np->server_buf overflowed.\n");
  14364.      fprintf(stderr,
  14365.              "More than %d bytes collected without CR/LF seen.\n",
  14366.              s_bytes);
  14367.      if (np->debug_file) {
  14368.        NNMdump(np,"Data collected so far",np->server_buf,s_bytes);
  14369.      }
  14370.      return(SERVER_BUFFER_ERROR);
  14371.    }
  14372.    if (character == '\0') {
  14373.      fprintf(stderr,
  14374. "Warning: null character found in data from server, changed to blank\n"
  14375.             );
  14376.      character = ' ';
  14377.    }
  14378.    s_buf[s_buf_index++] = (unsigned char)character;
  14379.  }
  14380.  s_buf[s_buf_index] = '\0';
  14381.  return(SERVER_READ_OK);
  14382. }
  14383.  
  14384. /****** Try to reconnect. ********************************************/
  14385.  
  14386. static Bool
  14387. try_to_reconnect(np)
  14388. Rstruc nncb     *np;
  14389. {
  14390.  
  14391.  if (np->closing_connection || np->reconnect_in_progress) return FALSE;
  14392.  
  14393.  if (!NNMrecon(np)) return FALSE;      /* Reconnect to server */
  14394.  
  14395.  /* have to reissue most recently written command */
  14396.  
  14397.  if (np->dont_reissue_socket_command) {
  14398.    NNMesrvr(np);           /* End server read */
  14399.  }
  14400.  else if (!NNMsockt(np)) { /* Send socket command to server */
  14401.    return FALSE;
  14402.  }
  14403.  
  14404.  WARN2("Successfully reconnected to server %s after disconnect.",
  14405.        np->nnserver);
  14406.  return TRUE;
  14407.  
  14408. }
  14409.  
  14410. /****** Try to authorize. ********************************************/
  14411.  
  14412. static Bool
  14413. try_to_authorize(np)
  14414. Rstruc nncb     *np;
  14415. {
  14416.  char            save_command[CLIENT_BUF_MSGSIZE+4];
  14417.  Bool            rc;
  14418.  
  14419.  if (np->closing_connection) return FALSE;
  14420.  
  14421.  NNMesrvr(np);           /* End server read */
  14422.  
  14423.  strcpy(save_command,np->nntp_command);
  14424.  rc = NNMgauth(np);                    /* Get authorization   */
  14425.  strcpy(np->nntp_command,save_command);
  14426.  if (!rc) return FALSE;
  14427.  
  14428.  /* have to reissue most recently written command */
  14429.  
  14430.  if (np->dont_reissue_socket_command) {
  14431.    NNMesrvr(np);           /* End server read */
  14432.  }
  14433.  else if (!NNMsockt(np)) { /* Send socket command to server */
  14434.    return FALSE;
  14435.  }
  14436.  
  14437.  return TRUE;
  14438.  
  14439. }
  14440.  
  14441. /****** Try to get something. ****************************************/
  14442.  
  14443. static int
  14444. try_to_get_something(np,pointer)
  14445. Rstruc nncb  *np;
  14446. char        **pointer;
  14447.  
  14448. {
  14449.  char              *sbufp;
  14450.  char              *p;
  14451.  int                scan_count;
  14452.  Bool               authorization_required;  /* put this in nncb? */
  14453.  
  14454.  authorization_required = FALSE;
  14455.  
  14456.  switch (socket_from_server(np)) {
  14457.    case SERVER_READ_OK:      break;
  14458.    case SERVER_READ_ERROR:   ERR2(
  14459.      "Lost server connection.  Failure reading data from server %s.",
  14460.                                   np->nnserver);
  14461.                              np->time_to_go_home = TRUE;
  14462.                              break;
  14463.    case SERVER_BUFFER_ERROR: ERR2(
  14464.  "Read error.  No linefeed character found in data from server %s.",
  14465.                                   np->nnserver);
  14466.                              np->time_to_go_home = TRUE;
  14467.                              break;
  14468.    case SERVER_NO_MORE:      np->server_has_something_pending = FALSE;
  14469.                              break;
  14470.  }
  14471.  
  14472.  if (np->connection_broken)  return GOT_DISCONNECT;
  14473.  if (np->time_to_go_home)    return GOT_NOTHING;
  14474.  if (np->dont_read && !np->server_has_something_pending)
  14475.                              return GOT_SOMETHING;
  14476.  
  14477.  np->something_to_print = TRUE;
  14478.  
  14479.  sbufp = np->server_buf;
  14480.  
  14481.  if (np->sending_text) {
  14482.    if (*sbufp == '.') {
  14483.      /*
  14484.      NNMdump(np,"Line that starts with a period",sbufp,strlen(sbufp));
  14485.      */
  14486.      switch (*(sbufp+1)) {
  14487.         case CARRIAGE_RETURN:
  14488.         case LINE_FEED:
  14489.         case '\0':
  14490.                   np->server_finished_replying = TRUE;
  14491.                /* np->something_to_print = FALSE; */
  14492.                   break;
  14493.         case '.':
  14494.                   break;
  14495.         default:
  14496.                   NNMdump(np,"Warning, bad period in line from server",
  14497.                           sbufp,strlen(sbufp));
  14498.                   break;
  14499.      }
  14500.    }
  14501.    else /* nothing - still sending that there text */ ;
  14502.  
  14503.    np->nntp_message_num  = NO_NNTP_MESSAGE_NUM;
  14504.    np->nntp_message_text = sbufp;
  14505.  }
  14506.  else {
  14507.        np->nntp_message_num = NO_NNTP_MESSAGE_NUM;
  14508.        scan_count = 0;
  14509.        sscanf(sbufp,"%d %n",&np->nntp_message_num,&scan_count);
  14510.        np->nntp_message_text = sbufp + scan_count;
  14511.        /*  NNMdump(np,"message_num", np->nntp_message_num, -2);  */
  14512.        /*  NNMdump(np,"message_text",np->nntp_message_text,-1);  */
  14513.        switch (np->nntp_message_num) {
  14514.           case 205:
  14515.           case 400:
  14516.        /* case 502: */
  14517.                    np->server_finished_replying = TRUE;
  14518.                    np->time_to_go_home = TRUE;
  14519.                    break;
  14520.           case 503:
  14521.                    np->server_finished_replying = TRUE;
  14522.                    np->connection_broken = TRUE;
  14523.                    np->time_to_go_home = TRUE;
  14524.                    np->g_bytes_returned = 0;
  14525.                    np->g_buf_index = -1;
  14526.                    np->something_to_print = FALSE;
  14527.                    break;
  14528.           case 380:
  14529.           case 480:
  14530.                    authorization_required = TRUE;
  14531.                    np->server_finished_replying = TRUE;
  14532.                    np->connection_broken = FALSE;
  14533.                    np->g_bytes_returned = 0;
  14534.                    np->g_buf_index = -1;
  14535.                    np->something_to_print = FALSE;
  14536.                    break;
  14537.           case 335:
  14538.           case 340:
  14539.                    np->server_finished_replying = TRUE;
  14540.                    np->receiving_text = TRUE;
  14541.                    break;
  14542.           case 100:
  14543.           case 199:
  14544.           case 215:
  14545.           case 220:
  14546.           case 221:
  14547.           case 222:
  14548.           case 230:
  14549.           case 231:
  14550.                    np->sending_text = TRUE;
  14551.                    break;
  14552.           case NO_NNTP_MESSAGE_NUM:
  14553.                    fprintf(stderr,
  14554.     "Error: No NNTP message ID number in response from server %s.\n",
  14555.                                   np->nnserver);
  14556.                    np->sending_text = TRUE;
  14557.                    np->receiving_text = FALSE;
  14558.                    break;
  14559.           default:
  14560.                    np->server_finished_replying = TRUE;
  14561.                    break;
  14562.    }
  14563.  }
  14564.  
  14565.  if (np->something_to_print) {
  14566.    /* Last character of output buffer is a CR without LF. */
  14567.    p = sbufp + strlen(sbufp)-1;
  14568.    if (p >= sbufp) {
  14569.      if (*p == CARRIAGE_RETURN) *p = '\0';
  14570.      else {
  14571.        fprintf(stderr,
  14572.    "Warning: No carriage return in data from server (%d bytes):\n%s\n",
  14573.                strlen(sbufp), sbufp);
  14574.          CRIT2(
  14575. "Carriage return expected but not seen in data from server %s.",
  14576.                np->nnserver);
  14577.           }
  14578.    }
  14579.    *pointer = sbufp;
  14580.  }
  14581.  
  14582.  if (np->debug_file) {
  14583.    NNMdump(np,"Response from server",sbufp,strlen(sbufp));
  14584.  }
  14585.  
  14586.  return (
  14587.          np->connection_broken        ? GOT_DISCONNECT
  14588.        : authorization_required       ? GOT_NOTAUTHORIZED
  14589.        : np->time_to_go_home          ? GOT_NOTHING
  14590.        :                                GOT_SOMETHING
  14591.         );
  14592. }
  14593.  
  14594. /****** Get server line. *********************************************/
  14595.  
  14596. Bool
  14597. NNMgsrvl(np,pointer)
  14598. Rstruc nncb  *np;
  14599. char        **pointer;
  14600. {
  14601.  int                tries;
  14602.  Bool               retry;
  14603.  Bool               rc;
  14604.  
  14605.  *pointer = NULL;
  14606.  
  14607.  if (np->receiving_text) { /* as when POSTing a news item... */
  14608.    return TRUE;
  14609.  }
  14610.  
  14611.  if (np->server_finished_replying) np->dont_read = TRUE;
  14612.  
  14613.  for (tries=0;tries<2;tries++) {
  14614.  
  14615.    switch (try_to_get_something(np,pointer)) {
  14616.      case GOT_SOMETHING:     return TRUE;
  14617.      case GOT_NOTHING:       return FALSE;
  14618.      case GOT_DISCONNECT:    if (try_to_reconnect(np)) continue;
  14619.                              else return FALSE;
  14620.      case GOT_NOTAUTHORIZED: if (try_to_authorize(np)) continue;
  14621.                              else return FALSE;
  14622.    }
  14623.  
  14624.  }
  14625.  
  14626. }
  14627.  
  14628. ./   ADD NAME=NNMIERR,SSI=01010042
  14629.  
  14630.  /********************************************************************/
  14631.  /*                                                                  */
  14632.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  14633.  /*                                                                  */
  14634.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  14635.  /* including the implied warranties of merchantability and fitness, */
  14636.  /* are expressly denied.                                            */
  14637.  /*                                                                  */
  14638.  /* Provided this copyright notice is included, this software may    */
  14639.  /* be freely distributed and not offered for sale.                  */
  14640.  /*                                                                  */
  14641.  /* Changes or modifications may be made and used only by the maker  */
  14642.  /* of same, and not further distributed.  Such modifications should */
  14643.  /* be mailed to the author for consideration for addition to the    */
  14644.  /* software and incorporation in subsequent releases.               */
  14645.  /*                                                                  */
  14646.  /********************************************************************/
  14647.  
  14648. #pragma  csect(code,  "NN@IERR ")
  14649. #pragma  csect(static,"NN$IERR ")
  14650. #include "nn.h"
  14651.  
  14652. /****** ISPF error handler. ******************************************/
  14653.  
  14654. void
  14655. NNMierr(np)
  14656. Rstruc nncb *np;
  14657. {
  14658.  char        errbuf[] = "DISPLAY PANEL(ISPTERM)";
  14659.  int         errlen;
  14660.  
  14661.  if (np->batch_mode) {
  14662.    fprintf(stderr,"ISPF services cannot be called from batch mode.\n");
  14663.    return;
  14664.  }
  14665.  
  14666.  errlen = strlen(errbuf);
  14667.  switch (ISPEXEC(&errlen,errbuf)) {
  14668.    case  0:
  14669.    case  4:
  14670.    case  8: break;
  14671.    default: fprintf(stderr,
  14672. "\n*** Severe ISPF error, cannot even display ISPTERM error panel.\n");
  14673.             fprintf(stderr,
  14674. "\n*** Return code from ISPF service is %d\n",np->ispfrc);
  14675.             break;
  14676.  }
  14677.  
  14678.  return; 
  14679. }
  14680.  
  14681. ./   ADD NAME=NNMIGET,SSI=01000014
  14682.  
  14683.  /********************************************************************/
  14684.  /*                                                                  */
  14685.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  14686.  /*                                                                  */
  14687.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  14688.  /* including the implied warranties of merchantability and fitness, */
  14689.  /* are expressly denied.                                            */
  14690.  /*                                                                  */
  14691.  /* Provided this copyright notice is included, this software may    */
  14692.  /* be freely distributed and not offered for sale.                  */
  14693.  /*                                                                  */
  14694.  /* Changes or modifications may be made and used only by the maker  */
  14695.  /* of same, and not further distributed.  Such modifications should */
  14696.  /* be mailed to the author for consideration for addition to the    */
  14697.  /* software and incorporation in subsequent releases.               */
  14698.  /*                                                                  */
  14699.  /********************************************************************/
  14700.  
  14701. #pragma  csect(code,  "NN@IGET ")
  14702. #pragma  csect(static,"NN$IGET ")
  14703. #include "nn.h"
  14704.  
  14705. /****** Retrieve the value of an ISPF variable into an integer. ******/
  14706.  
  14707. int
  14708. NNMiget(np,varname)
  14709. Rstruc nncb *np;
  14710. char        *varname;
  14711. {
  14712.  char        varbuf[16];
  14713.  int         vcopy_length;
  14714.  
  14715.  if (!strchr(varname,' ')) {
  14716.    fprintf(stderr,"NNMiget: no blank passed in var name\n");
  14717.    return FALSE;
  14718.  }
  14719.  
  14720.  vcopy_length = sizeof(varbuf);
  14721.  
  14722.  np->ispfrc = ISPLINK("VCOPY",varname,&vcopy_length,varbuf,"MOVE");
  14723.  switch (np->ispfrc) {
  14724.    case  0:
  14725.            varbuf[vcopy_length] = '\0';
  14726.            return atoi(varbuf);
  14727.    case  8:
  14728.            return 0;
  14729.    case 16:
  14730.            fprintf(stderr,
  14731.                    "Error: ISPF variable buffer too short to get %s\n",
  14732.                    varname);
  14733.            return 0;
  14734.    default:
  14735.            NNMierr(np);   /* handle ISPF error */
  14736.            return 0;
  14737.  }
  14738. }
  14739.  
  14740. ./   ADD NAME=NNMINIT,SSI=01480044
  14741.  
  14742.  /********************************************************************/
  14743.  /*                                                                  */
  14744.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  14745.  /*                                                                  */
  14746.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  14747.  /*                                                                  */
  14748.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  14749.  /* including the implied warranties of merchantability and fitness, */
  14750.  /* are expressly denied.                                            */
  14751.  /*                                                                  */
  14752.  /* Provided this copyright notice is included, this software may    */
  14753.  /* be freely distributed and not offered for sale.                  */
  14754.  /*                                                                  */
  14755.  /* Changes or modifications may be made and used only by the maker  */
  14756.  /* of same, and not further distributed.  Such modifications should */
  14757.  /* be mailed to the author for consideration for addition to the    */
  14758.  /* software and incorporation in subsequent releases.               */
  14759.  /*                                                                  */
  14760.  /********************************************************************/
  14761.  
  14762. #pragma  csect(code,  "NN@INIT ")
  14763. #pragma  csect(static,"NN$INIT ")
  14764. #include "nn.h"
  14765.  
  14766. #define ARGSIZE            72
  14767.  
  14768. #define clear_subject(X)   *(X)->selsubj = '\0'
  14769. #define subjectlt(X)       subjectcmp(X) < 0
  14770. #define NO_COMPARISON      TRUE
  14771. #define subjectmatch       NNMsumat(_subj,_ap->subject)
  14772. #define SEMI               ;
  14773. #define NOTHINGFUN(A)      /* */
  14774. #define ANYFUN(A)          SetUnknown(A)
  14775. #define NOFUN(A)           /* */
  14776. #define SETSUBJECTFUN(A)   _subj = set_subject(np,A->subject)
  14777.  
  14778. #define SEARCH_FIRST_TO_LAST(Apnew,Apold,Initfun,Compfun,Any) \
  14779.         SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
  14780.          (_wp = _wpfirst SEMI _wp <= _wplast SEMI _wp++),\
  14781.          (_vp = _vpfirst SEMI _vp <= _vplast SEMI _vp++))
  14782.  
  14783. #define SEARCH_LAST_TO_FIRST(Apnew,Apold,Initfun,Compfun,Any) \
  14784.         SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
  14785.          (_wp = _wplast SEMI _wp >= _wpfirst SEMI _wp--),\
  14786.          (_vp = _vplast SEMI _vp >= _vpfirst SEMI _vp--))
  14787.  
  14788. #define SEARCH_CURRENT_TO_FIRST(Apnew,Apold,Initfun,Compfun,Any) \
  14789.         SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
  14790.  (_wp = (np->current_sortvark-1) SEMI  _wp >= _wpfirst SEMI  _wp--),\
  14791.  (_vp = &GETVARK(gp,Apold->number)-1 SEMI  _vp >= _vpfirst SEMI  _vp--))
  14792.  
  14793. #define SEARCH_CURRENT_TO_LAST(Apnew,Apold,Initfun,Compfun,Any) \
  14794.         SEARCH(Apnew,Apold,Initfun##FUN,Compfun,Any##FUN,\
  14795.  (_wp = (np->current_sortvark+1) SEMI  _wp <= _wplast SEMI  _wp++),\
  14796.  (_vp = &GETVARK(gp,Apold->number)+1 SEMI  _vp <= _vplast SEMI  _vp++))
  14797.  
  14798. #define SEARCH(Apnew,Apold,Initexp,Compexp,Anyexp,Forwp,Forvp) \
  14799.  {\
  14800.   struct newsarticle  *_ap;\
  14801.   VARK                *_vp;\
  14802.   VARK                *_vpfirst;\
  14803.   VARK                *_vplast;\
  14804.   VARK               **_wp;\
  14805.   VARK               **_wpfirst;\
  14806.   VARK               **_wplast;\
  14807.   char                *_subj;\
  14808. \
  14809.   Initexp(Apold);\
  14810.   Apnew = NULL;\
  14811.    if (gp->sort_vector) {\
  14812.      _wpfirst = gp->sort_vector;\
  14813.      _wplast  = gp->sort_vector + gp->sort_count - 1;\
  14814.      for Forwp {\
  14815.        vp = *_wp;\
  14816.        Anyexp(*vp);\
  14817.        if (NNMcar(np,gp,0,vp,&_ap,&cd,RETRIEVE) && (Compexp)) {\
  14818.          np->current_sortvark = _wp;\
  14819.          Apnew = _ap;\
  14820.          break;\
  14821.        }\
  14822.      }\
  14823.    }\
  14824.    else if (gp->article_vector) {\
  14825.      _vpfirst = &GETVARKFIRST(gp);\
  14826.      _vplast  = &GETVARKLAST(gp);\
  14827.      for Forvp {\
  14828.        vp = _vp;\
  14829.        Anyexp(*vp);\
  14830.        if (NNMcar(np,gp,0,vp,&_ap,&cd,RETRIEVE) && (Compexp)) {\
  14831.          Apnew = _ap;\
  14832.          break;\
  14833.        }\
  14834.      }\
  14835.    }\
  14836.  }
  14837.  
  14838. #define ERROR_NEXT_ARTICLE              \
  14839.              "There are no further articles in this newsgroup."
  14840. #define ERROR_PREV_ARTICLE              \
  14841.              "There are no previous articles in this newsgroup."
  14842. #define ERROR_NEXT_TABLED_ARTICLE       \
  14843.  "There are no more news articles that satisfy the current criteria."
  14844. #define ERROR_PREV_TABLED_ARTICLE       \
  14845. "There are no previous news articles that satisfy the current criteria."
  14846. #define ERROR_NEXT_UNREAD_ARTICLE       \
  14847.             "There are no further unread articles in this newsgroup."
  14848. #define ERROR_PREV_UNREAD_ARTICLE       \
  14849.            "There are no previous unread articles in this newsgroup."
  14850. #define ERROR_NEXT_THREAD_ARTICLE       \
  14851.    np->show_all_articles ? \
  14852.    "There are no further articles on this subject in this newsgroup." \
  14853.    : \
  14854.    "No further UNREAD articles on this subject in this newsgroup."
  14855. #define ERROR_PREV_THREAD_ARTICLE       \
  14856.    np->show_all_articles ? \
  14857.   "There are no previous articles on this subject in this newsgroup." \
  14858.    : \
  14859.   "No previous UNREAD articles on this subject in this newsgroup."
  14860. #define ERROR_FIRST_THREAD_ARTICLE      \
  14861.    np->show_all_articles ? \
  14862.   "No other article could be found on this subject in this newsgroup." \
  14863.    : \
  14864.   "No UNREAD article could be found on this subject in this newsgroup."
  14865. #define ERROR_LAST_THREAD_ARTICLE       \
  14866.    np->show_all_articles ? \
  14867.   "No other article could be found on this subject in this newsgroup." \
  14868.    : \
  14869.   "No UNREAD article could be found on this subject in this newsgroup."
  14870. #define ERROR_NEW_THREAD_ARTICLE        \
  14871.   "There are no unread articles on other subjects in this newsgroup."
  14872.  
  14873. enum getop_option {
  14874.                    GETOP_NOMORE,
  14875.                    GETOP_ASIS,
  14876.                    GETOP_UPPERCASE,
  14877.                    GETOP_LOWERCASE,
  14878.                    GETOP_INTEGER
  14879.                   };
  14880.  
  14881. /****** Get the next operand of the command. *************************/
  14882.  
  14883. static Bool
  14884. getop(np,bufpp,argp,option)
  14885. Rstruc nncb            *np;
  14886. char                  **bufpp;
  14887. char                   *argp;
  14888. enum getop_option       option;
  14889. {
  14890.  register char         *icp;
  14891.  register char         *ocp;
  14892.  register int           olen;
  14893.  int                    maxlen;
  14894.  char                   quote;
  14895.  char                   work[12];
  14896.  
  14897.  icp = skip_ISPF_whitespace(*bufpp);
  14898.  if (!*icp) {                          /* if reached end of buffer  */
  14899.    *bufpp = icp;
  14900.    switch (option) {
  14901.      case GETOP_NOMORE:  return TRUE;            /* indicate no more */
  14902.      case GETOP_INTEGER: ERR1("A numeric integer value is required.");
  14903.                          return FALSE;
  14904.      default:            *argp = '\0';  /* set operand to null string*/
  14905.                          return TRUE;
  14906.    }
  14907.  }
  14908.  
  14909.  /* icp points to next argument in buffer */
  14910.  
  14911.  if (option == GETOP_NOMORE) return FALSE;   /* too many operands */
  14912.  
  14913.  if (option == GETOP_INTEGER) {
  14914.    ocp = work;
  14915.    maxlen = sizeof(work);
  14916.    quote = '\0';
  14917.   }
  14918.  else {
  14919.    ocp = argp;
  14920.    maxlen = ARGSIZE;
  14921.    switch (*icp) {
  14922.      case '\'':
  14923.      case '"' :  quote = *icp; break;
  14924.      default:    quote = '\0'; break;
  14925.    }
  14926.  }
  14927.  
  14928.  if (quote) {
  14929.    for (icp++,olen=0; ; icp++,ocp++,olen++) {
  14930.      if (!*icp) {
  14931.        ERR1("Beginning quote mark not matched by ending quote mark.");
  14932.        *bufpp = icp;
  14933.        return FALSE;
  14934.      }
  14935.      if (*icp == quote) {
  14936.        if (*(++icp) != quote) {
  14937.          *bufpp = icp;
  14938.          break;
  14939.        } 
  14940.      }
  14941.      if (olen <= maxlen) {
  14942.        switch (option) {
  14943.          case GETOP_LOWERCASE:  *ocp = tolower(*icp); break;
  14944.          case GETOP_UPPERCASE:  *ocp = toupper(*icp); break;
  14945.          default:               *ocp = *icp;          break;
  14946.        } 
  14947.      }
  14948.    }
  14949.    if (olen > maxlen) {
  14950.      ERR2("An operand longer than %d characters is not valid.", maxlen);
  14951.      return FALSE;
  14952.    }
  14953.  }
  14954.  else {
  14955.    find_ISPF_whitespace(*bufpp,icp);
  14956.    olen = *bufpp - icp;
  14957.  
  14958.    if (olen > maxlen) {
  14959.      ERR2("An operand longer than %d characters is not valid.", maxlen);
  14960.      return FALSE;
  14961.    }
  14962.  
  14963.    switch (option) {
  14964.      case GETOP_LOWERCASE: while (olen--) *ocp++ = tolower(*icp++);
  14965.                            break;
  14966.      case GETOP_UPPERCASE: while (olen--) *ocp++ = toupper(*icp++);
  14967.                            break;
  14968.      default:              while (olen--) *ocp++ = *icp++;
  14969.                            break;
  14970.    }
  14971.  }
  14972.  
  14973.  *ocp = '\0';
  14974.  
  14975.  if (option == GETOP_INTEGER) {
  14976.    if (*(work + strspn(work,"0123456789"))) {
  14977.      ERR1("A numeric integer value is required.");
  14978.      return FALSE;
  14979.    }
  14980.    *(int *)argp = atoi(work);
  14981.  }
  14982.  
  14983.  return TRUE;
  14984.  
  14985. }
  14986.  
  14987. /****** Subject compare, for locating by subject. ********************/
  14988.  
  14989. /* May want to emulate NNMstrlc for more efficiency.  All that is
  14990.  * needed is to add code to NNMstrlc to strip re's.
  14991.  */
  14992.  
  14993. static int
  14994. subjectcmp(a,b)
  14995. char        *a;
  14996. char        *b;
  14997. {
  14998.  char       *c1;
  14999.  char       *c2;
  15000.  int         re_count_1;
  15001.  int         re_count_2;
  15002.  int         answer;
  15003.  char        s2[257];
  15004.  
  15005.  /* arg 1 already lowercased */
  15006.  
  15007.  strncpy(s2,b,256);
  15008.  
  15009.  lowercase_and_strip_trailing_in_place(s2);
  15010.  
  15011.  c1 = a; 
  15012.  c2 = s2;
  15013.  
  15014.  re_count_1 = 0;
  15015.  while (!memcmp(c1,"re:",3)) {
  15016.    c1 = skip_whitespace(c1+3);
  15017.    re_count_1++;
  15018.  }
  15019.  re_count_2 = 0;
  15020.  while (!memcmp(c2,"re:",3)) {
  15021.    c2 = skip_whitespace(c2+3);
  15022.    re_count_2++;
  15023.  }
  15024.  
  15025.  if ((answer=strcmp(c1,c2)) != 0) return answer;
  15026.  else return re_count_1 - re_count_2;
  15027.  
  15028. }
  15029.  
  15030. /****** Mark all articles read. **************************************/
  15031.  
  15032. static Bool
  15033. mark_all_articles_read(np,gp,prompt)
  15034. Rstruc nncb          *np;
  15035. Rstruc newsgroup     *gp;
  15036. Fool                  prompt;
  15037. {
  15038.  int                  prc;
  15039.  VARK                *vp;
  15040.  VARK                *vpfirst;
  15041.  VARK                *vplast;
  15042.  
  15043.  /* Display panel asking if user really wants to do this. */
  15044.  
  15045.  if (prompt && !np->batch_mode) {
  15046.    (void)NNMivput(np,"NNMARK ","Read",-1);
  15047.    (void)NNMispf(np,"ADDPOP");
  15048.    prc = NNMdispl(np,"NNMPMARK");
  15049.    (void)NNMispf(np,"REMPOP");
  15050.    if (prc > 0) { /* see if user pressed END */
  15051.      WARN1("Operation cancelled, because you pressed END.");
  15052.      return TRUE;
  15053.    }
  15054.  }
  15055.  
  15056.  if (gp->article_vector) {
  15057.    vpfirst = &GETVARKFIRST(gp);
  15058.    vplast  = &GETVARKLAST(gp);
  15059.    for (vp = vpfirst; vp <= vplast; vp++) {
  15060.      SetRead(*vp);
  15061.    }
  15062.  }
  15063.  else {  /* no article vector, group was never selected */
  15064.    if (gp->saved_newsrc_line
  15065.     && gp->saved_newsrc_line != gp->saved_newsrc_data) {
  15066.      FREEMAIN(gp->saved_newsrc_line,"unparsed newsrc line");
  15067.    }
  15068.    gp->saved_newsrc_line = gp->saved_newsrc_data;
  15069.    sprintf(gp->saved_newsrc_data,"<%d",gp->high_number);
  15070.  }
  15071.  
  15072.  gp->unread_count = 0;
  15073.  
  15074.  WARN2("All of the articles in %s are now marked READ.",
  15075.        gp->name);
  15076.  
  15077.  return TRUE;
  15078. }
  15079.  
  15080. /****** Mark all articles unread. ************************************/
  15081.  
  15082. static Bool
  15083. mark_all_articles_unread(np,gp,prompt)
  15084. Rstruc nncb          *np;
  15085. Rstruc newsgroup     *gp;
  15086. Fool                  prompt;
  15087. {
  15088.  int                  prc;
  15089.  int                  uc;
  15090.  VARK                *vp;
  15091.  VARK                *vpfirst;
  15092.  VARK                *vplast;
  15093.  
  15094.  /* Display panel asking if user really wants to do this. */
  15095.  
  15096.  if (prompt && !np->batch_mode) {
  15097.    (void)NNMivput(np,"NNMARK ","Unread",-1);
  15098.    (void)NNMispf(np,"ADDPOP");
  15099.    prc = NNMdispl(np,"NNMPMARK");
  15100.    (void)NNMispf(np,"REMPOP");
  15101.    if (prc > 0) { /* see if user pressed END */
  15102.      WARN1("Operation cancelled, because you pressed END.");
  15103.      return TRUE;
  15104.    }
  15105.  }
  15106.  
  15107.  if (gp->article_vector) {
  15108.    uc = 0;
  15109.    vpfirst = &GETVARKFIRST(gp);
  15110.    vplast  = &GETVARKLAST(gp);
  15111.    for (vp = vpfirst; vp <= vplast; vp++) {
  15112.      /* Note that we don't mark missing articles unread. */
  15113.      if (IsPresent(*vp)) {
  15114.        if (IsRead(*vp)) uc++;
  15115.        SetUnread(*vp);
  15116.      }
  15117.    }
  15118.    gp->unread_count += uc;
  15119.  }
  15120.  else {  /* no article vector, group was never selected */
  15121.    if (gp->saved_newsrc_line
  15122.     && gp->saved_newsrc_line != gp->saved_newsrc_data) {
  15123.      FREEMAIN(gp->saved_newsrc_line,"unparsed newsrc line");
  15124.    }
  15125.    gp->saved_newsrc_line = gp->saved_newsrc_data;
  15126.    strcpy(gp->saved_newsrc_data,"<0");
  15127.    gp->unread_count = gp->article_count;
  15128.  }
  15129.  
  15130.  WARN2("All of the articles in %s are now marked UNREAD.",
  15131.        gp->name);
  15132.  
  15133.  return TRUE;
  15134. }
  15135.  
  15136. /****** Set subject. *************************************************/
  15137.  
  15138. static char *
  15139. set_subject(np,subj)
  15140. Rstruc nncb         *np;
  15141. char                *subj;
  15142. {
  15143.  char               *s;
  15144.  
  15145.  if (*np->selsubj) return np->selsubj;
  15146.  
  15147.  strncpy(np->selsubj, subj, sizeof(np->selsubj)-1);
  15148.  s = np->selsubj;
  15149.  lowercase_and_strip_trailing_in_place(s);
  15150.  while (!memcmp(s,"re:",3)) {
  15151.    s = skip_whitespace(s+3);
  15152.  }
  15153.  
  15154.  return s;
  15155.  
  15156. }
  15157.  
  15158. /****** Process newsgroup LOCATE command. ****************************/
  15159.  
  15160. static Bool
  15161. newsgroup_locate_command(np,gp,rest)
  15162. Rstruc nncb         *np;
  15163. Rstruc newsgroup    *gp;
  15164. char                *rest;
  15165. {
  15166.  char                string[ARGSIZE];
  15167.  
  15168.  /*
  15169.   * Pass back the group name to position to.  NNMVNG will do the rest.
  15170.   */
  15171.  
  15172.  if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  15173.  
  15174.  if (!*string || !getop(np,&rest,NULL,GETOP_NOMORE)) {
  15175.    ERR1("The LOCATE command requires exactly one operand.");
  15176.    return FALSE;
  15177.  }
  15178.  
  15179.  strcpy(np->newsgroup_locate_string, string);
  15180.  
  15181.  np->please_locate_group = TRUE;
  15182.  
  15183.  return TRUE;
  15184. }
  15185.  
  15186. /****** Process newsgroup ONLY command. ******************************/
  15187.  
  15188. static Bool
  15189. newsgroup_only_command(np,gp,rest)
  15190. Rstruc nncb         *np;
  15191. Rstruc newsgroup    *gp;
  15192. char                *rest;
  15193. {
  15194.  char                string[ARGSIZE];
  15195.  
  15196.  if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  15197.  
  15198.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  15199.    ERR1( 
  15200. "The ONLY command may have only one operand.  Try quoting the string."
  15201.        );
  15202.    return FALSE;
  15203.  }
  15204.  
  15205.  strcpy(np->newsgroup_only_string, string);
  15206.  
  15207.  np->newsgroup_criterion_changed = TRUE;
  15208.  
  15209.  if (*np->newsgroup_only_string) {
  15210.    WARN2(
  15211.     "To redisplay %s newsgroups, use ONLY command without operands.",
  15212.          (np->show_all_newsgroups ? "all" : "all registered"));
  15213.  }
  15214.  
  15215.  return TRUE;
  15216. }
  15217.  
  15218. /****** Process newsgroup FIND command. ******************************/
  15219.  
  15220. static Bool
  15221. newsgroup_find_command(np,gp,rest)
  15222. Rstruc nncb         *np;
  15223. Rstruc newsgroup    *gp;
  15224. char                *rest;
  15225. {
  15226.  Bool                string_given;
  15227.  Bool                option_given;
  15228.  char                string [ARGSIZE];
  15229.  char                opt    [ARGSIZE];
  15230.  
  15231.  /*
  15232.   * Pass back the group name to position to.  NNMVNG will do the rest.
  15233.   */
  15234.  
  15235.  if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  15236.  if (!getop(np,&rest,&opt   ,GETOP_LOWERCASE)) return FALSE;
  15237.  
  15238.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  15239.    ERR1( 
  15240.     "Too many operands on the FIND command.  Try quoting the string.");
  15241.    return FALSE;
  15242.  }
  15243.  
  15244.  string_given = *string;
  15245.  option_given = *opt;
  15246.  
  15247.  if (string_given) {
  15248.    strcpy(np->newsgroup_find_string,string);
  15249.  }
  15250.  else if (!*np->newsgroup_find_string) {
  15251.    ERR1( 
  15252.       "The FIND command requires a string the first time it is used.");
  15253.    return FALSE;
  15254.  }
  15255.  
  15256.  if (option_given) {
  15257.    if      (EQUAL(opt,"next"  )) np->newsgroup_find_option = FIND_NEXT;
  15258.    else if (EQUAL(opt,"first" )) np->newsgroup_find_option = FIND_FIRST;
  15259.    else if (EQUAL(opt,"prev"  )) np->newsgroup_find_option = FIND_PREV;
  15260.    else if (EQUAL(opt,"last"  )) np->newsgroup_find_option = FIND_LAST;
  15261.    else {
  15262.      ERR1("Unknown FIND option.  Specify NEXT, PREV, FIRST or LAST.");
  15263.      return FALSE;
  15264.    }
  15265.  }
  15266.  else {
  15267.    if (string_given)  np->newsgroup_find_option = FIND_NEXT;
  15268.    else switch (np->newsgroup_find_option) {
  15269.      case FIND_NEXT:  np->newsgroup_find_option = FIND_NEXT; break;
  15270.      case FIND_PREV:  np->newsgroup_find_option = FIND_PREV; break;
  15271.      case FIND_FIRST: np->newsgroup_find_option = FIND_NEXT; break;
  15272.      case FIND_LAST:  np->newsgroup_find_option = FIND_PREV; break;
  15273.      default:         np->newsgroup_find_option = FIND_NEXT; break;
  15274.    }
  15275.  }
  15276.  
  15277.  np->please_find_group = TRUE;
  15278.  np->repeat_find = (!string_given && !option_given);
  15279.  
  15280.  return TRUE;
  15281. }
  15282.  
  15283. /****** Process newsgroup EXTRACT command. ***************************/
  15284.  
  15285. static Bool
  15286. newsgroup_extract_command(np,gp,rest)
  15287. Rstruc nncb         *np;
  15288. struct newsgroup    *gp;
  15289. char                *rest;
  15290. {
  15291.  
  15292.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  15293.    ERR1("The EXTRACT command does not accept any operands.");
  15294.    return FALSE;
  15295.  }
  15296.  
  15297.  return NNMxlist(np,SEQ);  /* Extract newsgroup listing */
  15298.  
  15299. }
  15300.  
  15301. /****** Process newsgroup PRINT command. *****************************/
  15302.  
  15303. static Bool
  15304. newsgroup_print_command(np,gp,rest)
  15305. Rstruc nncb         *np;
  15306. struct newsgroup    *gp;
  15307. char                *rest;
  15308. {
  15309.  
  15310.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  15311.    ERR1("The PRINT command does not accept any operands.");
  15312.    return FALSE;
  15313.  }
  15314.  
  15315.  return NNMxlist(np,JES);  /* Extract newsgroup listing */
  15316.  
  15317. }
  15318.  
  15319. /****** Process newsgroup REG command. *******************************/
  15320.  
  15321. static Bool
  15322. newsgroup_reg_command(np,gp,rest)
  15323. Rstruc nncb         *np;
  15324. Rstruc newsgroup    *gp;
  15325. char                *rest;
  15326. {
  15327.  
  15328.  np->newsgroup_criterion_changed = TRUE;
  15329.  np->show_all_newsgroups = FALSE;
  15330.  if (*np->newsgroup_only_string) {
  15331.    WARN2(
  15332.     "To redisplay %s newsgroups, use ONLY command without operands.",
  15333.          (np->show_all_newsgroups ? "all" : "all registered"));
  15334.  }
  15335.  
  15336.  return TRUE;
  15337. }
  15338.  
  15339. /****** Process newsgroup ALL command. *******************************/
  15340.  
  15341. static Bool
  15342. newsgroup_all_command(np,gp,rest)
  15343. Rstruc nncb         *np;
  15344. Rstruc newsgroup    *gp;
  15345. char                *rest;
  15346. {
  15347.  
  15348.  np->newsgroup_criterion_changed = TRUE;
  15349.  np->show_all_newsgroups = TRUE;
  15350.  if (*np->newsgroup_only_string) {
  15351.    WARN2(
  15352.     "To redisplay %s newsgroups, use ONLY command without operands.",
  15353.          (np->show_all_newsgroups ? "all" : "all registered"));
  15354.  }
  15355.  
  15356.  return TRUE;
  15357. }
  15358.  
  15359. /****** Process newsgroup ORDER command. *****************************/
  15360.  
  15361. static Bool
  15362. newsgroup_order_command(np,gp,rest)
  15363. Rstruc nncb         *np;
  15364. Rstruc newsgroup    *gp;
  15365. char                *rest;
  15366. {
  15367.  char                string[ARGSIZE];
  15368.  char                order;
  15369.  
  15370.  /* Usage: ORDER A   -  display newsgroups in alphabetical order
  15371.   *        ORDER L   -  display newsgroups in NNTP list order
  15372.   *        ORDER N   -  display newsgroups in NEWSRC order
  15373.   */
  15374.  
  15375.  if (!getop(np,&rest,&string,GETOP_ASIS)) return FALSE;
  15376.  
  15377.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  15378.    ERR1( 
  15379.      "The ORDER command requires one operand: Alphabetical or List.");
  15380.    return FALSE;
  15381.  }
  15382.  
  15383.  switch (string[0]) {
  15384.    case 'a':
  15385.    case 'A': order = ALPHABETICAL_ORDER;  break;
  15386.    case 'l':
  15387.    case 'L': order = NNTP_LIST_ORDER;     break;
  15388.    case 'n':
  15389.    case 'N': order = NEWSRC_ORDER;        break;
  15390.    default:
  15391.              ERR1(
  15392.      "The ORDER command requires one operand: Alphabetical or List.");
  15393.                                           return FALSE;
  15394.  }
  15395.  
  15396.  if (order == NEWSRC_ORDER) {
  15397.    ERR1("Sorry, but NEWSRC order has not been implemented.");
  15398.    return FALSE;
  15399.  }
  15400.  
  15401.  if (order == NNTP_LIST_ORDER && !np->first_newsgroup_alt) {
  15402.    ERR1( 
  15403. "List order is valid only when newsgroup list retrieved from server."
  15404.        );
  15405.    return FALSE;
  15406.  }
  15407.  
  15408.  np->newsgroup_order_changed = TRUE;
  15409.  np->newsgroup_order = order;
  15410.  
  15411.  return TRUE;
  15412. }
  15413.  
  15414. /****** Process article LOCATE command. ******************************/
  15415.  
  15416. static Bool
  15417. article_locate_command(np,gp,rest)
  15418. Rstruc nncb          *np;
  15419. Rstruc newsgroup     *gp;
  15420. char                 *rest;
  15421. {
  15422.  struct newsarticle  *ap;
  15423.  VARK               **wp;
  15424.  VARK               **wpfirst;
  15425.  VARK               **wplast;
  15426.  int                  lnum;
  15427.  struct countdown     cd;
  15428.  char                 string[ARGSIZE];
  15429.  
  15430.  if (gp->sort_vector) {
  15431.    if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  15432.    if (!*string || !getop(np,&rest,NULL,GETOP_NOMORE)) {
  15433.      ERR1("The LOCATE command requires exactly one operand.");
  15434.      return FALSE;
  15435.    }
  15436.    /* Position to article with subject closest to requested subject */
  15437.    wpfirst = gp->sort_vector;
  15438.    wplast  = gp->sort_vector + gp->sort_count - 1;
  15439.    for (wp = wpfirst; wp < wplast; wp++) {
  15440.      if (NNMcar(np,gp,0,*wp,&ap,&cd,RETRIEVE)
  15441.       && subjectcmp(string,ap->subject) <= 0)
  15442.          break;
  15443.    }
  15444.    np->current_sortvark = wp;
  15445.    np->top_sorted_article = wp;
  15446.  }
  15447.  else {
  15448.    if (!getop(np,&rest,(char *)&lnum,GETOP_INTEGER)) return FALSE;
  15449.    if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  15450.      ERR1("The LOCATE command requires exactly one operand.");
  15451.      return FALSE;
  15452.    }
  15453.    /* Position to article with number closest to requested number */
  15454.    if (lnum < gp->vector_first) lnum = gp->vector_first;
  15455.    if (lnum > gp->vector_last)  lnum = gp->vector_last;
  15456.    np->top_article = lnum;
  15457.  }
  15458.  
  15459.  /* Note: We don't worry about whether that article, or any of the
  15460.   * articles between the current one and this one, are in the table.
  15461.   * When NNMvar regenerates the display, it will know that the top
  15462.   * article has changed and will figure it out.
  15463.   */
  15464.  
  15465.  return TRUE;
  15466. }
  15467.  
  15468. /****** Process article FIND command. ********************************/
  15469.  
  15470. static Bool
  15471. article_find_command(np,gp,rest)
  15472. Rstruc nncb         *np;
  15473. Rstruc newsgroup    *gp;
  15474. char                *rest;
  15475. {
  15476.  int                 save_top_article;
  15477.  VARK              **save_top_sorted_article;
  15478.  struct newsarticle *ap;
  15479.  VARK              **wp;
  15480.  VARK              **wpfirst;
  15481.  VARK              **wplast;
  15482.  VARK              **found_sorted_article;
  15483.  int                 found_article;
  15484.  int                 findbump;
  15485.  int                 anum;
  15486.  Bool                string_given;
  15487.  Bool                option_given;
  15488.  char                string [ARGSIZE];
  15489.  char                option [ARGSIZE];
  15490.  struct countdown    cd;
  15491.  
  15492.  if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  15493.  if (!getop(np,&rest,&option,GETOP_LOWERCASE)) return FALSE;
  15494.  
  15495.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  15496.    ERR1( 
  15497.     "Too many operands on the FIND command.  Try quoting the string.");
  15498.    return FALSE;
  15499.  }
  15500.  
  15501.  string_given = *string;
  15502.  option_given = *option;
  15503.  
  15504.  if (string_given) {
  15505.    strcpy(np->article_find_string,string);
  15506.  }
  15507.  else if (!*np->article_find_string) {
  15508.    ERR1( 
  15509.       "The FIND command requires a string the first time it is used.");
  15510.    return FALSE;
  15511.  }
  15512.  
  15513.  if (option_given) {
  15514.    if      (EQUAL(option,"next" )) np->article_find_option = FIND_NEXT;
  15515.    else if (EQUAL(option,"first")) np->article_find_option = FIND_FIRST;
  15516.    else if (EQUAL(option,"prev" )) np->article_find_option = FIND_PREV;
  15517.    else if (EQUAL(option,"last" )) np->article_find_option = FIND_LAST;
  15518.    else {
  15519.      ERR1("Unknown FIND option.  Specify NEXT, PREV, FIRST or LAST.");
  15520.      return FALSE;
  15521.    }
  15522.  }
  15523.  else {
  15524.    if (string_given) np->article_find_option = FIND_NEXT;
  15525.    else switch (np->article_find_option) {
  15526.      case FIND_NEXT:  np->article_find_option = FIND_NEXT; break;
  15527.      case FIND_PREV:  np->article_find_option = FIND_PREV; break;
  15528.      case FIND_FIRST: np->article_find_option = FIND_NEXT; break;
  15529.      case FIND_LAST:  np->article_find_option = FIND_PREV; break;
  15530.      default:         np->article_find_option = FIND_NEXT; break;
  15531.    }
  15532.  }
  15533.  
  15534.  np->article_repeat_find = !string_given;
  15535.  
  15536.  /* do the find here */
  15537.  
  15538.  if (gp->sort_vector) {
  15539.    save_top_sorted_article = np->top_sorted_article;
  15540.    wpfirst = gp->sort_vector;
  15541.    wplast  = gp->sort_vector + gp->sort_count - 1;
  15542.    switch (np->article_find_option) {
  15543.      case FIND_NEXT:
  15544.                      findbump = 1;
  15545.                      if (np->article_repeat_find) {
  15546.                        if (np->article_text_not_found)
  15547.                           np->top_sorted_article = wpfirst;
  15548.                        else np->top_sorted_article++;
  15549.                      }
  15550.                      break;
  15551.      case FIND_PREV:
  15552.                      findbump = -1;
  15553.                      if (np->article_repeat_find) {
  15554.                        if (np->article_text_not_found)
  15555.                           np->top_sorted_article = wplast;
  15556.                        else np->top_sorted_article--;
  15557.                      }
  15558.                      break;
  15559.      case FIND_FIRST:
  15560.                      np->top_sorted_article = wpfirst;
  15561.                      findbump = 1;
  15562.                      break;
  15563.      case FIND_LAST:
  15564.                      np->top_sorted_article = wplast;
  15565.                      findbump = -1;
  15566.                      break;
  15567.    }
  15568.  
  15569.    found_sorted_article = NULL;
  15570.    for (wp = np->top_sorted_article;
  15571.         wp <= wplast && wp >= wpfirst; wp += findbump) {
  15572.      /* ap = VARK2PARTICLE(**wp); */
  15573.      if (NNMcar(np,gp,0,*wp,&ap,&cd,RETRIEVE)
  15574.       && NNMstrlc(ap->subject,np->article_find_string)) {
  15575.        found_sorted_article = wp;
  15576.        break;
  15577.      }
  15578.    }
  15579.    if (!found_sorted_article) {
  15580.      np->top_sorted_article = save_top_sorted_article;
  15581.      np->article_text_not_found = TRUE;
  15582.    }
  15583.    else {
  15584.      np->top_sorted_article = found_sorted_article;
  15585.      np->article_text_not_found = FALSE;
  15586.    }
  15587.  }
  15588.  else {  /* not sorted */
  15589.    save_top_article = np->top_article;
  15590.    switch (np->article_find_option) {
  15591.      case FIND_NEXT:
  15592.                      findbump = 1;
  15593.                      if (np->article_repeat_find) {
  15594.                        if (np->article_text_not_found)
  15595.                           np->top_article = gp->vector_first;
  15596.                        else np->top_article++;
  15597.                      }
  15598.                      break;
  15599.      case FIND_PREV:
  15600.                      findbump = -1;
  15601.                      if (np->article_repeat_find) {
  15602.                        if (np->article_text_not_found)
  15603.                           np->top_article = gp->vector_last;
  15604.                        else np->top_article--;
  15605.                      }
  15606.                      break;
  15607.      case FIND_FIRST:
  15608.                      np->top_article = gp->vector_first;
  15609.                      findbump = 1;
  15610.                      break;
  15611.      case FIND_LAST:
  15612.                      np->top_article = gp->vector_last;
  15613.                      findbump = -1;
  15614.                      break;
  15615.    }
  15616.    if (!np->top_article) return FALSE;
  15617.  
  15618.    cd.do_update = (np->updatefreq >= 0);
  15619.    cd.done      = 0;
  15620.    cd.to_do     = -1;
  15621.  
  15622.    found_article = 0;
  15623.  
  15624.    for (anum = np->top_article;
  15625.         anum <= gp->vector_last && anum >= gp->vector_first;
  15626.         anum += findbump) {
  15627.      if (NNMcar(np,gp,anum,NULL,&ap,&cd,RETRIEVE)
  15628.       && NNMstrlc(ap->subject,np->article_find_string)) {
  15629.        found_article = anum;
  15630.        break;
  15631.      }
  15632.    }
  15633.    if (found_article == 0) {
  15634.      np->top_article = save_top_article;
  15635.      np->article_text_not_found = TRUE;
  15636.    }
  15637.    else {
  15638.      np->top_article = found_article;
  15639.      np->article_text_not_found = FALSE;
  15640.    }
  15641.  
  15642.  }
  15643.  
  15644.  if (np->article_text_not_found) {
  15645.    ERR3("No %s articles with subject of: '%s'",
  15646.         (findbump > 0 ? "more" : "previous"),
  15647.         np->article_find_string);
  15648.  }
  15649.  else {
  15650.    WARN1("Article found;\
  15651. The article whose subject contains the desired text tops the display.");
  15652.  }
  15653.  
  15654.  return TRUE;
  15655.  
  15656. }
  15657.  
  15658. /****** Process article ONLY command. *******************************/
  15659.  
  15660. static Bool
  15661. article_only_command(np,gp,rest)
  15662. Rstruc nncb         *np;
  15663. Rstruc newsgroup    *gp;
  15664. char                *rest;
  15665. {
  15666.  char                string[ARGSIZE];
  15667.  VARK               *vp;
  15668.  VARK               *vpfirst;
  15669.  VARK               *vplast;
  15670.  
  15671.  if (!getop(np,&rest,&string,GETOP_LOWERCASE)) return FALSE;
  15672.  
  15673.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  15674.    ERR1( 
  15675. "The ONLY command may have only one operand.  Try quoting the string."
  15676.        );
  15677.    return FALSE;
  15678.  }
  15679.  
  15680.  strcpy(np->article_only_string, string);
  15681.  
  15682.  if (gp->article_vector) {
  15683.    vpfirst = &GETVARKFIRST(gp);
  15684.    vplast  = &GETVARKLAST(gp);
  15685.    for (vp = vpfirst; vp <= vplast; vp++) {
  15686.      SetUnknown(*vp);
  15687.    }
  15688.  }
  15689.  
  15690.  np->article_criterion_changed = TRUE;
  15691.  np->top_article = gp->vector_first;
  15692.  np->top_sorted_article = gp->sort_vector;
  15693.  if (*np->article_only_string) {
  15694.    WARN1(
  15695. "To show articles with all subjects, use ONLY command with no operand."
  15696.         );
  15697.  }
  15698.  
  15699.  return TRUE;
  15700. }
  15701.  
  15702. /****** Process article SORT command. *******************************/
  15703.  
  15704. static Bool
  15705. article_sort_command(np,gp,rest)
  15706. Rstruc nncb         *np;
  15707. Rstruc newsgroup    *gp;
  15708. char                *rest;
  15709. {
  15710.  Bool                by_subject;
  15711.  char                string[ARGSIZE];
  15712.  
  15713.  /* Usage: SORT Subject
  15714.   *        SORT Number
  15715.   */
  15716.  
  15717.  if (!getop(np,&rest,&string,GETOP_ASIS)) return FALSE;
  15718.  
  15719.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  15720.    ERR1("The SORT command requires one operand: Subject or Number.");
  15721.    return FALSE;
  15722.  }
  15723.  
  15724.  switch (string[0]) {
  15725.    case 's':
  15726.    case 'S': by_subject = TRUE;  break;
  15727.    case 'n':
  15728.    case 'N': by_subject = FALSE; break;
  15729.    default:
  15730.      ERR1("The SORT command requires one operand: Subject or Number.");
  15731.      return FALSE;
  15732.  }
  15733.  
  15734.  if (!gp->article_vector) {
  15735.    ERR1("There are no articles in this newsgroup to sort.");
  15736.    return TRUE;
  15737.  }
  15738.  
  15739.  if (by_subject) {
  15740.    if (!NNMsort(np,gp)) return FALSE;
  15741.  }
  15742.  else {
  15743.    if (gp->sort_vector) {
  15744.      FREEMAIN(gp->sort_vector,"sort vector");
  15745.      gp->sort_vector = NULL;
  15746.    }
  15747.  }
  15748.  
  15749.  np->article_criterion_changed = TRUE;
  15750.  np->top_article = 0;
  15751.  np->top_sorted_article = gp->sort_vector;
  15752.  
  15753.  return TRUE;
  15754. }
  15755.  
  15756. /****** Process article EXTRACT command. *****************************/
  15757.  
  15758. static Bool
  15759. article_extract_command(np,gp,rest)
  15760. Rstruc nncb         *np;
  15761. Rstruc newsgroup    *gp;
  15762. char                *rest;
  15763. {
  15764.  Bool                asked_for;
  15765.  char                nnchoice[2];
  15766.  
  15767.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  15768.    ERR1("The EXTRACT command does not accept any operands.");
  15769.    return FALSE;
  15770.  }
  15771.  
  15772.  (void)NNMivput(np,"NNLGROUP ",gp->name,-1);
  15773.  
  15774.  /* Display panel asking whether it's list of titles or log of text */
  15775.  
  15776.  asked_for = TRUE;
  15777.  
  15778.  (void)NNMispf(np,"ADDPOP");
  15779.  for (;;) {
  15780.    if (NNMdispl(np,"NNMPEXNT") > 0) {
  15781.      asked_for = FALSE;
  15782.      break;
  15783.    }
  15784.    (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
  15785.    if (*nnchoice == '?') {
  15786.      ERR1("Invalid choice;\
  15787. Move the cursor to a selection (or type S next to it) and press ENTER."
  15788.          );
  15789.    }
  15790.    else break;
  15791.  }
  15792.  
  15793.  (void)NNMispf(np,"REMPOP");
  15794.  if (!asked_for) return TRUE;
  15795.  
  15796.  switch (*nnchoice) {
  15797.    case '1':  return NNMxartt(np,gp,SEQ);
  15798.    case '2':  return NNMxartx(np,gp,SEQ);
  15799.    case '3':  return NNMxartx(np,gp,PDS);
  15800.  }
  15801.  
  15802.  return FALSE;
  15803. }
  15804.  
  15805. /****** Process article PRINT command. *******************************/
  15806.  
  15807. static Bool
  15808. article_print_command(np,gp,rest)
  15809. Rstruc nncb         *np;
  15810. Rstruc newsgroup    *gp;
  15811. char                *rest;
  15812. {
  15813.  Bool                asked_for;
  15814.  char                nnchoice[2];
  15815.  
  15816.  if (!getop(np,&rest,NULL,GETOP_NOMORE)) {
  15817.    ERR1("The PRINT command does not accept any operands.");
  15818.    return FALSE;
  15819.  }
  15820.  
  15821.  (void)NNMivput(np,"NNLGROUP ",gp->name,-1);
  15822.  
  15823.  /* Display panel asking whether it's list of titles or log of text */
  15824.  
  15825.  asked_for = TRUE;
  15826.  
  15827.  (void)NNMispf(np,"ADDPOP");
  15828.  for (;;) {
  15829.    if (NNMdispl(np,"NNMPPRNT") > 0) {
  15830.      asked_for = FALSE;
  15831.      break;
  15832.    }
  15833.    (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
  15834.    if (*nnchoice == '?') {
  15835.      ERR1("Invalid choice;\
  15836. Move the cursor to a selection (or type S next to it) and press ENTER."
  15837.          );
  15838.    }
  15839.    else break;
  15840.  }
  15841.  
  15842.  (void)NNMispf(np,"REMPOP");
  15843.  if (!asked_for) return TRUE;
  15844.  
  15845.  switch (*nnchoice) {
  15846.    case '1':  return NNMxartt(np,gp,JES);
  15847.    case '2':  return NNMxartx(np,gp,JES);
  15848.  }
  15849.  
  15850.  return FALSE;
  15851. }
  15852.  
  15853. /****** Process article MARKALL command. *****************************/
  15854.  
  15855. static Bool
  15856. article_markall_command(np,gp,rest)
  15857. Rstruc nncb          *np;
  15858. Rstruc newsgroup     *gp;
  15859. char                 *rest;
  15860. {
  15861.  struct newsarticle  *ap;
  15862.  VARK                *vp;
  15863.  VARK                *vpfirst;
  15864.  VARK                *vplast;
  15865.  int                  prc;
  15866.  Bool                 allp;
  15867.  struct countdown     cd;
  15868.  char                 nnchoice[9];
  15869.  
  15870.  cd.do_update = (np->updatefreq >= 0);
  15871.  cd.done      = 0;
  15872.  cd.to_do     = -1;
  15873.  
  15874.  if (!gp->article_vector) {
  15875.    ERR1("There are no articles to mark.");
  15876.    return TRUE;
  15877.  }
  15878.  
  15879.  /* Display panel asking what user really wants to do. */
  15880.  
  15881.  strcpy(nnchoice,"");
  15882.  
  15883.  for (;;) {
  15884.    (void)NNMivput(np,"NNMARK ","Read",-1);
  15885.    (void)NNMispf(np,"ADDPOP");
  15886.    prc = NNMdispl(np,"NNMPMALL");
  15887.    (void)NNMispf(np,"REMPOP");
  15888.    if (prc > 0) strcpy(nnchoice,"3");
  15889.    else (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
  15890.    switch (nnchoice[0]) {
  15891.      case '1': allp = TRUE;  break;
  15892.      case '2': allp = FALSE; break;
  15893.      case '3': ERR1("Operation cancelled by your request.");
  15894.                return TRUE;
  15895.      default:
  15896.                 ERR1("Invalid choice;\
  15897. Move the cursor to a selection (or type S next to it) and press ENTER."
  15898.          );
  15899.                 continue;
  15900.    }
  15901.    break;
  15902.  }
  15903.  
  15904.  /*
  15905.   * This isn't really too good.  It means that ALL the articles
  15906.   * will have to be retrieved in order to mark them read.
  15907.   *
  15908.   * A better way would be to set a flag in the VARK saying
  15909.   * "marked read" rather than "read", so that future fetches
  15910.   * would put the article in the table but set the action to
  15911.   * "read".  We're going to need a "cross-posted-read" flag
  15912.   * that's independent of fetching the article anyhow...
  15913.   *
  15914.   * How about this?  Add a new article status, ARTICLE_DUMMY,
  15915.   * set when unique storage is allocated for a struct newsarticle
  15916.   * but neither the headers nor the body have been retrieved.
  15917.   * It would have null values in it, but:
  15918.   *
  15919.   * the action field could be set when article is marked (un)read
  15920.   * the subject field could be set from an XHDR request
  15921.   * likewise for date, etc. fields
  15922.   *
  15923.   * If NNMrarh is asked to retrieve such an article, it will fill
  15924.   * it in with stuff.
  15925.   *
  15926.   * NNMcar could be modified to be asked to create dummy articles
  15927.   * instead of retrieving headers for them.  This would be done if
  15928.   * just going through and setting ap->actions or ap->subjects.
  15929.   */
  15930.  
  15931.  vpfirst = &GETVARKFIRST(gp);
  15932.  vplast  = &GETVARKLAST(gp);
  15933.  
  15934.  if (allp) {
  15935.    mark_all_articles_read(np,gp,FALSE);
  15936.    for (vp = vpfirst; vp <= vplast; vp++) {
  15937.      if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
  15938.        if (ap) ap->action = READ;
  15939.      }
  15940.    }
  15941.    gp->unread_count = 0;
  15942.  }
  15943.  else {
  15944.    for (vp = vpfirst; vp <= vplast; vp++) {
  15945.      if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
  15946.        NNMmarr(np,gp,vp);                /* mark article read */
  15947.      }
  15948.    }
  15949.  }
  15950.  
  15951.  return TRUE;
  15952. }
  15953.  
  15954. /****** Process article UNMARKALL command. ***************************/
  15955.  
  15956. static Bool
  15957. article_unmarkall_command(np,gp,rest)
  15958. Rstruc nncb          *np;
  15959. Rstruc newsgroup     *gp;
  15960. char                 *rest;
  15961. {
  15962.  struct newsarticle  *ap;
  15963.  VARK                *vp;
  15964.  VARK                *vpfirst;
  15965.  VARK                *vplast;
  15966.  int                  prc;
  15967.  Bool                 allp;
  15968.  char                 nnchoice[9];
  15969.  struct countdown     cd;
  15970.  
  15971.  cd.do_update = (np->updatefreq >= 0);
  15972.  cd.done      = 0;
  15973.  cd.to_do     = -1;
  15974.  
  15975.  if (!gp->article_vector) {
  15976.    ERR1("There are no articles to mark.");
  15977.    return TRUE;
  15978.  }
  15979.  
  15980.  /* Display panel asking what user really wants to do. */
  15981.  
  15982.  strcpy(nnchoice,"");
  15983.  
  15984.  for (;;) {
  15985.    (void)NNMivput(np,"NNMARK ","Unread",-1);
  15986.    (void)NNMispf(np,"ADDPOP");
  15987.    prc = NNMdispl(np,"NNMPMALL");
  15988.    (void)NNMispf(np,"REMPOP");
  15989.    if (prc > 0) strcpy(nnchoice,"3");
  15990.    else (void)NNMivget(np,"NNCHOICE ",nnchoice,sizeof(nnchoice));
  15991.    switch (nnchoice[0]) {
  15992.      case '1': allp = TRUE;  break;
  15993.      case '2': allp = FALSE; break;
  15994.      case '3': ERR1("Operation cancelled by your request.");
  15995.                return TRUE;
  15996.      default:
  15997.                 ERR1("Invalid choice;\
  15998. Move the cursor to a selection (or type S next to it) and press ENTER."
  15999.          );
  16000.                 continue;
  16001.    }
  16002.    break;
  16003.  }
  16004.  
  16005.  /* see comments under previous function.  they apply here too */
  16006.  
  16007.  vpfirst = &GETVARKFIRST(gp);
  16008.  vplast  = &GETVARKLAST(gp);
  16009.  
  16010.  if (allp) {
  16011.    mark_all_articles_unread(np,gp,FALSE);
  16012.    for (vp = vpfirst; vp <= vplast; vp++) {
  16013.      if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
  16014.        if (ap) ap->action = UNREAD;
  16015.      }
  16016.    }
  16017.    gp->unread_count = gp->article_count;
  16018.  }
  16019.  else {
  16020.    for (vp = vpfirst; vp <= vplast; vp++) {
  16021.      if (NNMcar(np,gp,0,vp,&ap,&cd,MARK_ONLY)) { /* choose article */
  16022.        NNMmaru(np,gp,vp);                /* mark article read */
  16023.      }
  16024.    }
  16025.  }
  16026.  
  16027.  return TRUE;
  16028. }
  16029.  
  16030. /****** Process article TITLES command. ******************************/
  16031.  
  16032. static Bool
  16033. article_titles_command(np,gp,rest)
  16034. Rstruc nncb         *np;
  16035. Rstruc newsgroup    *gp;
  16036. char                *rest;
  16037. {
  16038.  
  16039.  /* Actually, this probably ought to be a NOP, since we always ought to
  16040.   * be retrieving article titles as we display a screenful.
  16041.   * Since this command retrieves ALL titles, it's kind of wasteful.
  16042.   */
  16043.  
  16044.  (void)NNMrart(np,gp,TRUE,TRUE); /* Retrieve *all* article titles */
  16045.  
  16046.  return TRUE;
  16047.  
  16048. }
  16049.  
  16050. /****** Process article QUERY command. *******************************/
  16051.  
  16052. static Bool
  16053. article_query_command(np,gp,rest)
  16054. Rstruc nncb         *np;
  16055. Rstruc newsgroup    *gp;
  16056. char                *rest;
  16057. {
  16058.  
  16059.  NNMqng(np,gp);                          /* Query newsgroup */
  16060.  
  16061.  return TRUE;
  16062. }
  16063.  
  16064. /****** Process POST command. ****************************************/
  16065.  
  16066. static Bool
  16067. general_post_command(np,gp,rest)
  16068. Rstruc nncb         *np;
  16069. Rstruc newsgroup    *gp;
  16070. char                *rest;
  16071. {
  16072.  
  16073.  NNMdpost(np,gp,NULL);      /* Do posting (no article up to follow) */
  16074.  
  16075.  return TRUE;
  16076. }
  16077.  
  16078. /****** Process MAIL command. ****************************************/
  16079.  
  16080. static Bool
  16081. general_mail_command(np,gp,rest)
  16082. Rstruc nncb         *np;
  16083. Rstruc newsgroup    *gp;
  16084. char                *rest;
  16085. {
  16086.  
  16087.  NNMdmail(np,gp,NULL);      /* Do mailing (no article to to reply) */
  16088.  
  16089.  return TRUE;
  16090. }
  16091.  
  16092. /****** Process TEST command. ****************************************/
  16093.  
  16094. static Bool
  16095. general_test_command(np,gp,rest)
  16096. Rstruc nncb         *np;
  16097. struct newsgroup    *gp;
  16098. char                *rest;
  16099. {
  16100.  
  16101.  np->test_mode = TRUE;
  16102.  __ctest(rest);
  16103.  
  16104.  return TRUE;
  16105. }
  16106.  
  16107. /****** Process NNTP command. ****************************************/
  16108.  
  16109. static Bool
  16110. general_nntp_command(np,gp,rest)
  16111. Rstruc nncb         *np;
  16112. struct newsgroup    *gp;
  16113. char                *rest;
  16114. {
  16115.  
  16116.  (void)NNMdnntp(np,rest);      /* Do native NNTP */
  16117.  
  16118.  return TRUE;
  16119. }
  16120.  
  16121. /****** Process SAVE command. ****************************************/
  16122.  
  16123. static Bool
  16124. general_save_command(np,gp,rest)
  16125. Rstruc nncb         *np;
  16126. struct newsgroup    *gp;
  16127. char                *rest;
  16128. {
  16129.  
  16130.  return NNMsave(np,rest);  /* Save NEWSRC file */
  16131.  
  16132. }
  16133.  
  16134. /****** Process OPTIONS command. *************************************/
  16135.  
  16136. static Bool
  16137. general_options_command(np,gp,rest)
  16138. Rstruc nncb         *np;
  16139. struct newsgroup    *gp;
  16140. char                *rest;
  16141. {
  16142.  char                option[ARGSIZE];
  16143.  
  16144.  if (!getop(np,&rest,&option,GETOP_LOWERCASE)) return FALSE;
  16145.  
  16146.  NNMdsopt(np,option);         /* Do "set options" function */
  16147.  
  16148.  return TRUE;
  16149. }
  16150.  
  16151. /****** Process QUIT command. ****************************************/
  16152.  
  16153. static Bool
  16154. general_quit_command(np,gp,rest)
  16155. Rstruc nncb         *np;
  16156. struct newsgroup    *gp;
  16157. char                *rest;
  16158. {
  16159.  
  16160.  np->quit = TRUE;
  16161.  
  16162.  return TRUE;
  16163. }
  16164.  
  16165. /****** Process CRASHNNMVS command. **********************************/
  16166.  
  16167. static Bool
  16168. general_crashnnmvs_command(np,gp,rest)
  16169. Rstruc nncb         *np;
  16170. struct newsgroup    *gp;
  16171. char                *rest;
  16172. {
  16173.  
  16174.  fprintf(stderr,"Terminating NNMVS with extreme prejudice.\n");
  16175.  
  16176.  exit(999);
  16177.  
  16178. }
  16179.  
  16180. /****** Process DEBUG command. ***************************************/
  16181.  
  16182. static Bool
  16183. general_debug_command(np,gp,rest)
  16184. Rstruc nncb         *np;
  16185. struct newsgroup    *gp;
  16186. char                *rest;
  16187. {
  16188.  
  16189.  if (!np->debug_mode) {
  16190.  
  16191.    if (!(np->debug_file = fopen("dd:nndebug","a"))) {
  16192.      perror("debug file (DD NNDEBUG)");
  16193.    }
  16194.    else np->debug_mode = TRUE;
  16195.  }
  16196.  
  16197.  return TRUE;
  16198. }
  16199.  
  16200. /****** Process NODEBUG command. *************************************/
  16201.  
  16202. static Bool
  16203. general_nodebug_command(np,gp,rest)
  16204. Rstruc nncb         *np;
  16205. struct newsgroup    *gp;
  16206. char                *rest;
  16207. {
  16208.  
  16209.  if (np->debug_mode) {
  16210.    if (np->debug_file) {
  16211.      if (fclose(np->debug_file) < 0) {
  16212.        fprintf(stderr,"Error closing debug file (DD NNDEBUG)\n");
  16213.      }
  16214.      np->debug_file = NULL;
  16215.    }
  16216.    np->debug_mode = FALSE;
  16217.  }
  16218.  
  16219.  return TRUE;
  16220. }
  16221.  
  16222. /****** Process DISCONNECT command. *********************************/
  16223.  
  16224. static Bool
  16225. general_disconnect_command(np,gp,rest)
  16226. Rstruc nncb         *np;
  16227. struct newsgroup    *gp;
  16228. char                *rest;
  16229. {
  16230.  char               *dummy = "503 Simulated disconnect.";
  16231.  int                 index;
  16232.  
  16233.  /* fake a disconnect condition by sending an NNTP "QUIT".
  16234.   * The next attempt to communicate with the socket will get
  16235.   * the simulated response instead of what it expected.
  16236.   */
  16237.  
  16238.  strcpy(np->nntp_command,"QUIT");
  16239.  if (!NNMsockt(np)) return FALSE;  /* Send socket command to server */
  16240.  
  16241.  index = strlen(dummy);
  16242.  strcpy(np->g_buf+1,dummy);
  16243.  np->g_buf[index+1] = CARRIAGE_RETURN;
  16244.  np->g_buf[index+2] = LINE_FEED;
  16245.  np->g_bytes_returned = index+3;
  16246.  np->g_buf_index = 0;
  16247.  
  16248.  return TRUE;
  16249. }
  16250.  
  16251. /****** Process newsgroup S selection. *******************************/
  16252.  
  16253. static Bool
  16254. newsgroup_s_selection(np,gp)
  16255. Rstruc nncb          *np;
  16256. Rstruc newsgroup     *gp;
  16257. {
  16258.  
  16259.  np->show_all_articles       = FALSE;
  16260.  np->bypass_header_retrieval = FALSE;
  16261.  np->unread_articles_only    = FALSE;
  16262.  
  16263.  return(NNMpng(np,gp,FALSE,FALSE));                /* Pick newsgroup */
  16264.  
  16265. }
  16266.  
  16267. /****** Process newsgroup N selection. *******************************/
  16268.  
  16269. static Bool
  16270. newsgroup_n_selection(np,gp)
  16271. Rstruc nncb          *np;
  16272. Rstruc newsgroup     *gp;
  16273. {
  16274.  
  16275.  np->show_all_articles       = FALSE;
  16276.  np->bypass_header_retrieval = FALSE;
  16277.  np->unread_articles_only    = TRUE;
  16278.  
  16279.  return(NNMpng(np,gp,FALSE,FALSE));                /* Pick newsgroup */
  16280.  
  16281. }
  16282.  
  16283. /****** Process newsgroup A selection. *******************************/
  16284.  
  16285. static Bool
  16286. newsgroup_a_selection(np,gp)
  16287. Rstruc nncb          *np;
  16288. Rstruc newsgroup     *gp;
  16289. {
  16290.  
  16291.  np->show_all_articles       = TRUE;
  16292.  np->bypass_header_retrieval = FALSE;
  16293.  np->unread_articles_only    = FALSE;
  16294.  
  16295.  return(NNMpng(np,gp,FALSE,FALSE));                /* Pick newsgroup */
  16296.  
  16297. }
  16298.  
  16299. /****** Process newsgroup Z selection. *******************************/
  16300.  
  16301. static Bool
  16302. newsgroup_z_selection(np,gp)
  16303. Rstruc nncb          *np;
  16304. Rstruc newsgroup     *gp;
  16305. {
  16306.  
  16307.  np->show_all_articles       = TRUE;
  16308.  np->bypass_header_retrieval = TRUE;
  16309.  np->unread_articles_only    = FALSE;
  16310.  
  16311.  return(NNMpng(np,gp,FALSE,FALSE));                /* Pick newsgroup */
  16312.  
  16313. }
  16314.  
  16315. /****** Process newsgroup $ selection. *******************************/
  16316.  
  16317. static Bool
  16318. newsgroup_dollar_selection(np,gp)
  16319. Rstruc nncb          *np;
  16320. Rstruc newsgroup     *gp;
  16321. {
  16322.  
  16323.  np->show_all_articles       = FALSE;
  16324.  np->bypass_header_retrieval = FALSE;
  16325.  np->unread_articles_only    = FALSE;
  16326.  
  16327.  return(NNMpng(np,gp,TRUE,TRUE)); /* pick group, get titles, sort it */
  16328.  
  16329. }
  16330.  
  16331. /****** Process newsgroup @ selection. *******************************/
  16332.  
  16333. static Bool
  16334. newsgroup_atsign_selection(np,gp)
  16335. Rstruc nncb          *np;
  16336. Rstruc newsgroup     *gp;
  16337. {
  16338.  
  16339.  np->show_all_articles       = TRUE;
  16340.  np->bypass_header_retrieval = FALSE;
  16341.  np->unread_articles_only    = FALSE;
  16342.  
  16343.  return(NNMpng(np,gp,TRUE,TRUE)); /* pick group, get titles, sort it */
  16344.  
  16345. }
  16346.  
  16347. /****** Process newsgroup Q selection. *******************************/
  16348.  
  16349. static Bool
  16350. newsgroup_q_selection(np,gp)
  16351. Rstruc nncb         *np;
  16352. Rstruc newsgroup    *gp;
  16353. {
  16354.  
  16355.  NNMqng(np,gp);                          /* Query newsgroup */
  16356.  
  16357.  return TRUE;
  16358. }
  16359.  
  16360. /****** Process newsgroup R selection. *******************************/
  16361.  
  16362. static Bool
  16363. newsgroup_r_selection(np,gp)
  16364. Rstruc nncb          *np;
  16365. Rstruc newsgroup     *gp;
  16366. {
  16367.  
  16368.  gp->registered = 1;
  16369.  
  16370.  WARN2("Newsgroup %s registered (subscribed).", gp->name);
  16371.  
  16372.  return TRUE;
  16373. }
  16374.  
  16375. /****** Process newsgroup D selection. *******************************/
  16376.  
  16377. static Bool
  16378. newsgroup_d_selection(np,gp)
  16379. Rstruc nncb          *np;
  16380. Rstruc newsgroup     *gp;
  16381. {
  16382.  
  16383.  gp->registered = 0;
  16384.  
  16385.  WARN2("Newsgroup %s deregistered (unsubscribed).", gp->name);
  16386.  
  16387.  return TRUE;
  16388. }
  16389.  
  16390. /****** Process newsgroup M selection. *******************************/
  16391.  
  16392. static Bool
  16393. newsgroup_m_selection(np,gp)
  16394. Rstruc nncb          *np;
  16395. Rstruc newsgroup     *gp;
  16396. {
  16397.  
  16398.  return mark_all_articles_read(np,gp,TRUE);
  16399.  
  16400. }
  16401.  
  16402. /****** Process newsgroup U selection. *******************************/
  16403.  
  16404. static Bool
  16405. newsgroup_u_selection(np,gp)
  16406. Rstruc nncb          *np;
  16407. Rstruc newsgroup     *gp;
  16408. {
  16409.  
  16410.  return mark_all_articles_unread(np,gp,TRUE);
  16411.  
  16412. }
  16413.  
  16414. /****** Process article E selection. *********************************/
  16415.  
  16416. static Bool
  16417. article_e_selection(np,ap)
  16418. Rstruc nncb          *np;
  16419. Rstruc newsarticle   *ap;
  16420. {
  16421.  
  16422.  np->extract_file = NULL;
  16423.  if (!NNMpick(np,ap)) return FALSE;
  16424.  NNMdoit(np,ap,'E');
  16425.  return TRUE;
  16426.  
  16427. }
  16428.  
  16429. /****** Process article F selection. *********************************/
  16430.  
  16431. static Bool
  16432. article_f_selection(np,ap)
  16433. Rstruc nncb          *np;
  16434. Rstruc newsarticle   *ap;
  16435. {
  16436.  
  16437.  if (!NNMpick(np,ap)) return FALSE;
  16438.  NNMdoit(np,ap,'F');
  16439.  return TRUE;
  16440.  
  16441. }
  16442.  
  16443. /****** Process article C selection. *********************************/
  16444.  
  16445. static Bool
  16446. article_c_selection(np,ap)
  16447. Rstruc nncb          *np;
  16448. Rstruc newsarticle   *ap;
  16449. {
  16450.  
  16451.  if (!NNMpick(np,ap)) return FALSE;
  16452.  NNMdoit(np,ap,'C');
  16453.  return TRUE;
  16454.  
  16455. }
  16456.  
  16457. /****** Process article M selection. *********************************/
  16458.  
  16459. static Bool
  16460. article_m_selection(np,ap)
  16461. Rstruc nncb         *np;
  16462. Rstruc newsarticle  *ap;
  16463. {
  16464.  Rstruc newsgroup   *gp = np->current_newsgroup;
  16465.  VARK               *vp = &GETVARK(gp,ap->number);
  16466.  
  16467.  NNMmarr(np,gp,vp);                          /* Make article read */
  16468.  
  16469.  return TRUE;
  16470. }
  16471.  
  16472. /****** Process article P selection. *********************************/
  16473.  
  16474. static Bool
  16475. article_p_selection(np,ap)
  16476. Rstruc nncb          *np;
  16477. Rstruc newsarticle   *ap;
  16478. {
  16479.  
  16480.  np->extract_file = NULL;
  16481.  if (!NNMpick(np,ap)) return FALSE;
  16482.  NNMdoit(np,ap,'P');
  16483.  return TRUE;
  16484.  
  16485. }
  16486.  
  16487. /****** Process article Q selection. *********************************/
  16488.  
  16489. static Bool
  16490. article_q_selection(np,ap)
  16491. Rstruc nncb         *np;
  16492. Rstruc newsarticle  *ap;
  16493. {
  16494.  
  16495.  return NNMqar(np,ap);
  16496. }
  16497.  
  16498. /****** Process article R selection. *********************************/
  16499.  
  16500. static Bool
  16501. article_r_selection(np,ap)
  16502. Rstruc nncb          *np;
  16503. Rstruc newsarticle   *ap;
  16504. {
  16505.  
  16506.  if (!NNMpick(np,ap)) return FALSE;
  16507.  NNMdoit(np,ap,'R');
  16508.  return TRUE;
  16509.  
  16510. }
  16511.  
  16512. /****** Process article S selection. *********************************/
  16513.  
  16514. static Bool
  16515. article_s_selection(np,ap)
  16516. Rstruc nncb          *np;
  16517. Rstruc newsarticle   *ap;
  16518. {
  16519.  Rstruc newsgroup    *gp = np->current_newsgroup;
  16520.  Rstruc newsarticle  *ap1 = ap;
  16521.  Rstruc newsarticle  *ap2 = NULL;
  16522.  VARK                *vp;
  16523.  VARK                *vp1;
  16524.  enum article_cookie  cookie;
  16525.  Bool                 save_show_all_articles;
  16526.  struct countdown     cd;
  16527.  
  16528.  np->extract_file = NULL;
  16529.  clear_subject(np);
  16530.  
  16531.  /* Continue as long as NEXT/PREV/UNREAD requests occur. */
  16532.  
  16533.  for (;;) {
  16534.    if (!NNMpick(np,ap1)) return FALSE;  /* Pick article to process */
  16535.    NNMdoit(np,ap1,'S');                 /* Process article */
  16536.    cookie = np->another_article;
  16537.    if (cookie == NULL_ARTICLE_COOKIE) break;
  16538.    cd.do_update = (np->updatefreq >= 0);
  16539.    cd.done      = 0;
  16540.    cd.to_do     = -1;
  16541.    switch (cookie) {
  16542.      case REDISPLAY_ARTICLE:
  16543.           ap2 = NULL;
  16544.           break;
  16545.      case UNREAD_THIS_ARTICLE:
  16546.           clear_subject(np);
  16547.           vp1 = &GETVARK(gp,ap1->number);
  16548.           NNMmaru(np,gp,vp1);            /* Make article unread */
  16549.           return TRUE;
  16550.      case NEXT_ARTICLE:
  16551.           save_show_all_articles = np->show_all_articles;
  16552.           np->show_all_articles = TRUE;
  16553.           SEARCH_CURRENT_TO_LAST(ap2,ap1,NOTHING,NO_COMPARISON,ANY);
  16554.           np->show_all_articles = save_show_all_articles;
  16555.           if (!ap2) ERR1(ERROR_NEXT_ARTICLE);
  16556.           break;
  16557.      case PREV_ARTICLE:
  16558.           save_show_all_articles = np->show_all_articles;
  16559.           np->show_all_articles = TRUE;
  16560.           SEARCH_CURRENT_TO_FIRST(ap2,ap1,NOTHING,NO_COMPARISON,ANY);
  16561.           np->show_all_articles = save_show_all_articles;
  16562.           if (!ap2) ERR1(ERROR_PREV_ARTICLE);
  16563.           break;
  16564.      case NEXT_TABLED_ARTICLE:
  16565.           SEARCH_CURRENT_TO_LAST(ap2,ap1,NOTHING,IsEligible(*vp),NO);
  16566.           if (!ap2) ERR1(ERROR_NEXT_TABLED_ARTICLE);
  16567.           break;
  16568.      case PREV_TABLED_ARTICLE:
  16569.           SEARCH_CURRENT_TO_FIRST(ap2,ap1,NOTHING,IsEligible(*vp),NO);
  16570.           if (!ap2) ERR1(ERROR_PREV_TABLED_ARTICLE);
  16571.           break;
  16572.      case NEXT_UNREAD_ARTICLE:
  16573.           SEARCH_CURRENT_TO_LAST(ap2,ap1,NOTHING,IsUnread(*vp),NO);
  16574.           if (!ap2) ERR1(ERROR_NEXT_UNREAD_ARTICLE);
  16575.           break;
  16576.      case PREV_UNREAD_ARTICLE:
  16577.           SEARCH_CURRENT_TO_FIRST(ap2,ap1,NOTHING,IsUnread(*vp),NO);
  16578.           if (!ap2) ERR1(ERROR_PREV_UNREAD_ARTICLE);
  16579.           break;
  16580.      case NEXT_THREAD_ARTICLE:
  16581.           SEARCH_CURRENT_TO_LAST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
  16582.           if (!ap2) {
  16583.             ERR1(ERROR_NEXT_THREAD_ARTICLE);
  16584.             clear_subject(np);
  16585.           }
  16586.           break;
  16587.      case PREV_THREAD_ARTICLE:
  16588.           SEARCH_CURRENT_TO_FIRST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
  16589.           if (!ap2) {
  16590.             ERR1(ERROR_PREV_THREAD_ARTICLE);
  16591.             clear_subject(np);
  16592.           }
  16593.           break;
  16594.      case FIRST_THREAD_ARTICLE:
  16595.           SEARCH_FIRST_TO_LAST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
  16596.           if (!ap2) {
  16597.             ERR1(ERROR_FIRST_THREAD_ARTICLE);
  16598.             clear_subject(np);
  16599.           }
  16600.           break;
  16601.      case LAST_THREAD_ARTICLE:
  16602.           SEARCH_LAST_TO_FIRST(ap2,ap1,SETSUBJECT,subjectmatch,NO);
  16603.           if (!ap2) {
  16604.             ERR1(ERROR_LAST_THREAD_ARTICLE);
  16605.             clear_subject(np);
  16606.           }
  16607.           break;
  16608.      case NEW_THREAD_ARTICLE:
  16609.           SEARCH_FIRST_TO_LAST(ap2,ap1,SETSUBJECT,
  16610.                                IsUnread(*vp) && !subjectmatch,NO);
  16611.           clear_subject(np);
  16612.           if (!ap2) ERR1(ERROR_NEW_THREAD_ARTICLE);
  16613.           else (void)set_subject(np,ap2->subject);
  16614.           break;
  16615.      default:
  16616.           clear_subject(np);
  16617.           ap2 = NULL;
  16618.           break;
  16619.    }
  16620.  
  16621.    if (ap2) {
  16622.      /* Bump display to article to be seen */
  16623.      if (gp->sort_vector)
  16624.           np->top_sorted_article = np->current_sortvark;
  16625.      else np->top_article = ap2->number;
  16626.      SetEligible(*vp); /* Force it eligible for display */
  16627.      ap1 = ap2;
  16628.    }
  16629.  }
  16630.  
  16631.  clear_subject(np);
  16632.  
  16633.  return TRUE;
  16634.  
  16635. }
  16636.  
  16637. /****** Process article U selection. *********************************/
  16638.  
  16639. static Bool
  16640. article_u_selection(np,ap)
  16641. Rstruc nncb         *np;
  16642. Rstruc newsarticle  *ap;
  16643. {
  16644.  Rstruc newsgroup   *gp = np->current_newsgroup;
  16645.  VARK               *vp = &GETVARK(gp,ap->number);
  16646.  
  16647.  NNMmaru(np,gp,vp);                         /* Make article unread */
  16648.  
  16649.  return TRUE;
  16650. }
  16651.  
  16652. /*********************************************************************/
  16653.  
  16654. void
  16655. NNMinit(np)
  16656. Rstruc nncb            *np;
  16657. {
  16658.  
  16659.  static struct tabledesc newsgroup_display_table;
  16660.  static struct tabledesc article_display_table;
  16661.  static struct tabledesc text_display_table;
  16662.  static struct cmddesc   newsgroup_commands[] = {
  16663.                           {"L          ",newsgroup_locate_command   },
  16664.                           {"LOC        ",newsgroup_locate_command   },
  16665.                           {"LOCATE     ",newsgroup_locate_command   },
  16666.                           {"F          ",newsgroup_find_command     },
  16667.                           {"FIND       ",newsgroup_find_command     },
  16668.                           {"EXT        ",newsgroup_extract_command  },
  16669.                           {"EXTRACT    ",newsgroup_extract_command  },
  16670.                           {"PRT        ",newsgroup_print_command    },
  16671.                           {"PRNT       ",newsgroup_print_command    },
  16672.                           {"REG        ",newsgroup_reg_command      },
  16673.                           {"REGISTER   ",newsgroup_reg_command      },
  16674.                           {"ALL        ",newsgroup_all_command      },
  16675.                           {"ONLY       ",newsgroup_only_command     },
  16676.                           {"ORDER      ",newsgroup_order_command    },
  16677.                           {"           ",NULL}
  16678.                          };
  16679.  static struct cmddesc   article_commands[] = {
  16680.                           {"L          ",article_locate_command     },
  16681.                           {"LOC        ",article_locate_command     },
  16682.                           {"LOCATE     ",article_locate_command     },
  16683.                           {"F          ",article_find_command       },
  16684.                           {"FIND       ",article_find_command       },
  16685.                           {"EXT        ",article_extract_command    },
  16686.                           {"EXTRACT    ",article_extract_command    },
  16687.                           {"PRT        ",article_print_command      },
  16688.                           {"PRNT       ",article_print_command      },
  16689.                           {"MARKALL    ",article_markall_command    },
  16690.                           {"UNMARKALL  ",article_unmarkall_command  },
  16691.                           {"TITLE      ",article_titles_command     },
  16692.                           {"TITLES     ",article_titles_command     },
  16693.                           {"ONLY       ",article_only_command       },
  16694.                           {"Q          ",article_query_command      },
  16695.                           {"QUERY      ",article_query_command      },
  16696.                           {"SORT       ",article_sort_command       },
  16697.                           {"           ",NULL}
  16698.                          };
  16699.  
  16700.  static struct cmddesc   general_commands[] = {
  16701.                           {"POST       ",general_post_command       },
  16702.                           {"MAIL       ",general_mail_command       },
  16703.                           {"TEST       ",general_test_command       },
  16704.                           {"NNTP       ",general_nntp_command       },
  16705.                           {"SAVE       ",general_save_command       },
  16706.                           {"OPTIONS    ",general_options_command    },
  16707.                           {"OPT        ",general_options_command    },
  16708.                           {"QUIT       ",general_quit_command       },
  16709.                           {"DEBUG      ",general_debug_command      },
  16710.                           {"NODEBUG    ",general_nodebug_command    },
  16711.                           {"DISCONNECT ",general_disconnect_command },
  16712.                           {"CRASHNNMVS ",general_crashnnmvs_command },
  16713.                           {"           ",NULL}
  16714.                          };
  16715.  
  16716.  static struct seldesc   newsgroup_selections[] = {
  16717.                           {'S',newsgroup_s_selection },
  16718.                           {'N',newsgroup_n_selection },
  16719.                           {'A',newsgroup_a_selection },
  16720.                           {'R',newsgroup_r_selection },
  16721.                           {'D',newsgroup_d_selection },
  16722.                           {'M',newsgroup_m_selection },
  16723.                           {'U',newsgroup_u_selection },
  16724.                           {'Q',newsgroup_q_selection },
  16725.                        /* {'Z',newsgroup_z_selection }, */
  16726.                           {'$',newsgroup_dollar_selection },
  16727.                           {'@',newsgroup_atsign_selection },
  16728.                           {' ',NULL}
  16729.                          };
  16730.  static struct seldesc   article_selections[] = {
  16731.                           {'S',article_s_selection },
  16732.                           {'E',article_e_selection },
  16733.                           {'P',article_p_selection },
  16734.                           {'M',article_m_selection },
  16735.                           {'U',article_u_selection },
  16736.                           {'F',article_f_selection },
  16737.                           {'R',article_r_selection },
  16738.                           {'Q',article_q_selection },
  16739.                           {'C',article_c_selection },
  16740.                           {' ',NULL}
  16741.                          };
  16742.  
  16743.  static struct tablevector all_display_tables;
  16744.  
  16745.  newsgroup_display_table.command_variable   = "NNGCMD ";
  16746.  newsgroup_display_table.first_cmddesc      = newsgroup_commands;
  16747.  newsgroup_display_table.next_cmddesc       = general_commands;
  16748.  newsgroup_display_table.first_seldesc      = newsgroup_selections;
  16749.  
  16750.  article_display_table.command_variable     = "NNTCMD ";
  16751.  article_display_table.first_cmddesc        = article_commands;
  16752.  article_display_table.next_cmddesc         = general_commands;
  16753.  article_display_table.first_seldesc        = article_selections;
  16754.  
  16755.  text_display_table.command_variable        = "ZCMD ";
  16756.  text_display_table.first_cmddesc           = NULL; /* filled later */
  16757.  text_display_table.next_cmddesc            = general_commands;
  16758.  text_display_table.first_seldesc           = NULL;
  16759.  
  16760.  all_display_tables.newsgroup_display_table = &newsgroup_display_table;
  16761.  all_display_tables.article_display_table   = &article_display_table;
  16762.  all_display_tables.text_display_table      = &text_display_table;
  16763.  
  16764.  np->display_table_vector = &all_display_tables;
  16765.  
  16766.  return; 
  16767. }
  16768. ./   ADD NAME=NNMISPF,SSI=01010058
  16769.  
  16770.  /********************************************************************/
  16771.  /*                                                                  */
  16772.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  16773.  /*                                                                  */
  16774.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  16775.  /* including the implied warranties of merchantability and fitness, */
  16776.  /* are expressly denied.                                            */
  16777.  /*                                                                  */
  16778.  /* Provided this copyright notice is included, this software may    */
  16779.  /* be freely distributed and not offered for sale.                  */
  16780.  /*                                                                  */
  16781.  /* Changes or modifications may be made and used only by the maker  */
  16782.  /* of same, and not further distributed.  Such modifications should */
  16783.  /* be mailed to the author for consideration for addition to the    */
  16784.  /* software and incorporation in subsequent releases.               */
  16785.  /*                                                                  */
  16786.  /********************************************************************/
  16787.  
  16788. #pragma  csect(code,  "NN@ISPF ")
  16789. #pragma  csect(static,"NN$ISPF ")
  16790. #include "nn.h"
  16791.  
  16792. /****** Call ISPF service. *******************************************/
  16793.  
  16794. Bool
  16795. NNMispf(np,ispfbuf)
  16796. Rstruc nncb *np;
  16797. char        *ispfbuf;
  16798. {
  16799.  int         ispflen;
  16800.  
  16801.  ispflen = strlen(ispfbuf);
  16802.  
  16803. #ifndef ISPFV2
  16804.  if (np->test_mode) {
  16805. #endif
  16806.    if (ispflen >= 6
  16807.       && (memcmp(ispfbuf,"ADDPOP",6) == 0
  16808.        || memcmp(ispfbuf,"REMPOP",6) == 0)) {
  16809.      np->ispfrc = 0;
  16810.      return TRUE;
  16811.    }
  16812. #ifndef ISPFV2
  16813.  }
  16814. #endif
  16815.  
  16816.  np->ispfrc = ISPEXEC(&ispflen,ispfbuf);
  16817.  if (np->ispfrc > 8) {
  16818.  
  16819.    /* Ignore ADDPOP and REMPOP errors, especially if they are due to
  16820.       ISPF V3 not being active. */
  16821.  
  16822.    if (np->ispfrc == 20
  16823.     && np->debug_mode == FALSE
  16824.     && ispflen >= 6
  16825.     && (memcmp(ispfbuf,"ADDPOP",6) == 0
  16826.      || memcmp(ispfbuf,"REMPOP",6) == 0)) {
  16827.      return TRUE;
  16828.    }
  16829.  
  16830.    NNMierr(np);             /* handle ISPF error */
  16831.    return FALSE;
  16832.  }
  16833.  return TRUE;
  16834. }
  16835.  
  16836. ./   ADD NAME=NNMIVGET,SSI=01000032
  16837.  
  16838.  /********************************************************************/
  16839.  /*                                                                  */
  16840.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  16841.  /*                                                                  */
  16842.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  16843.  /* including the implied warranties of merchantability and fitness, */
  16844.  /* are expressly denied.                                            */
  16845.  /*                                                                  */
  16846.  /* Provided this copyright notice is included, this software may    */
  16847.  /* be freely distributed and not offered for sale.                  */
  16848.  /*                                                                  */
  16849.  /* Changes or modifications may be made and used only by the maker  */
  16850.  /* of same, and not further distributed.  Such modifications should */
  16851.  /* be mailed to the author for consideration for addition to the    */
  16852.  /* software and incorporation in subsequent releases.               */
  16853.  /*                                                                  */
  16854.  /********************************************************************/
  16855.  
  16856. #pragma  csect(code,  "NN@IVGET")
  16857. #pragma  csect(static,"NN$IVGET")
  16858. #include "nn.h"
  16859.  
  16860. /****** Retrieve the value of an ISPF variable. **********************/
  16861.  
  16862. Bool
  16863. NNMivget(np,varname,varbuf,varbuflen)
  16864. Rstruc nncb *np;
  16865. char        *varname;
  16866. char        *varbuf;
  16867. int          varbuflen;
  16868. {
  16869.  int         vcopy_length;
  16870.  
  16871.  if (!strchr(varname,' ')) {
  16872.    fprintf(stderr,"NNMivget: no blank passed in var name\n");
  16873.    return FALSE;
  16874.  }
  16875.  
  16876.  /*
  16877.   * If varbuflen is negative, that means that the value is not to be
  16878.   * treated as a C string, and the null character is not to be
  16879.   * appended to the resulting value.  This is used for hex values
  16880.   * (like addresses) that are stored in ISPF table row variables.
  16881.   */
  16882.  
  16883.  if (varbuflen < 0)  vcopy_length = -varbuflen;
  16884.  else vcopy_length = varbuflen;
  16885.  
  16886.  /* Note that on entry, vcopy_length is an integer that contains
  16887.     the length of the buffer.  On return it is updated to the length
  16888.     of the value returned.  Since we have to stick a null character
  16889.     on the end of it for C, the actual buffer passed must be at least
  16890.     one character longer than the length as defined to ISPF.
  16891.  */
  16892.  
  16893.  np->ispfrc = ISPLINK("VCOPY",varname,&vcopy_length,varbuf,"MOVE");
  16894.  switch (np->ispfrc) {
  16895.    case  0:
  16896.            if (varbuflen >= 0) varbuf[vcopy_length] = '\0';
  16897.            return TRUE;
  16898.    case  8:
  16899.            strcpy(varbuf,"");
  16900.            return TRUE;
  16901.    case 16:
  16902.            fprintf(stderr,
  16903.                    "Error: ISPF variable buffer too short to get %s\n",
  16904.                    varname);
  16905.            return FALSE;
  16906.    default:
  16907.            NNMierr(np);   /* handle ISPF error */
  16908.            return FALSE;
  16909.  }
  16910. }
  16911.  
  16912. ./   ADD NAME=NNMIVPUT,SSI=01000043
  16913.  
  16914.  /********************************************************************/
  16915.  /*                                                                  */
  16916.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  16917.  /*                                                                  */
  16918.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  16919.  /* including the implied warranties of merchantability and fitness, */
  16920.  /* are expressly denied.                                            */
  16921.  /*                                                                  */
  16922.  /* Provided this copyright notice is included, this software may    */
  16923.  /* be freely distributed and not offered for sale.                  */
  16924.  /*                                                                  */
  16925.  /* Changes or modifications may be made and used only by the maker  */
  16926.  /* of same, and not further distributed.  Such modifications should */
  16927.  /* be mailed to the author for consideration for addition to the    */
  16928.  /* software and incorporation in subsequent releases.               */
  16929.  /*                                                                  */
  16930.  /********************************************************************/
  16931.  
  16932. #pragma  csect(code,  "NN@IVPUT")
  16933. #pragma  csect(static,"NN$IVPUT")
  16934. #include "nn.h"
  16935.  
  16936. /****** Set the value of an ISPF variable. ***************************/
  16937.  
  16938. Bool
  16939. NNMivput(np,varname,varbuf,varlen)
  16940. Rstruc nncb *np;
  16941. char        *varname;
  16942. char        *varbuf;
  16943. int         varlen;
  16944. {
  16945.  int         vreplace_length;
  16946.  
  16947.  vreplace_length = (varlen < 0 ? strlen(varbuf) : varlen);
  16948.  
  16949.  np->ispfrc = ISPLINK("VREPLACE",varname,&vreplace_length,varbuf);
  16950.  switch (np->ispfrc) {
  16951.    case  0:
  16952.            return TRUE;
  16953.    case 16:
  16954.            fprintf(stderr,
  16955.                    "Error: ISPF variable buffer too short to put %s\n",
  16956.                    varname);
  16957.            return FALSE;
  16958.    default:
  16959.            NNMierr(np);   /* handle ISPF error */
  16960.            return FALSE;
  16961.  }
  16962. }
  16963.  
  16964. ./   ADD NAME=NNMMAIN,SSI=01020026
  16965.  
  16966.  /********************************************************************/
  16967.  /*                                                                  */
  16968.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  16969.  /*                                                                  */
  16970.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  16971.  /*                                                                  */
  16972.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  16973.  /* including the implied warranties of merchantability and fitness, */
  16974.  /* are expressly denied.                                            */
  16975.  /*                                                                  */
  16976.  /* Provided this copyright notice is included, this software may    */
  16977.  /* be freely distributed and not offered for sale.                  */
  16978.  /*                                                                  */
  16979.  /* Changes or modifications may be made and used only by the maker  */
  16980.  /* of same, and not further distributed.  Such modifications should */
  16981.  /* be mailed to the author for consideration for addition to the    */
  16982.  /* software and incorporation in subsequent releases.               */
  16983.  /*                                                                  */
  16984.  /********************************************************************/
  16985.  
  16986.  /********************************************************************/
  16987.  /*                                                                  */
  16988.  /*                             NNMVS                                */
  16989.  /*                                                                  */
  16990.  /*                   MVS news reader dialog driver                  */
  16991.  /*                                                                  */
  16992.  /*                            Author:                               */
  16993.  /*                   Steve Bacher <seb@draper.com>                  */
  16994.  /*                                                                  */
  16995.  /*                    Enhancements contributed by:                  */
  16996.  /*                  Dale Ingold <snoddi@mvs.sas.com>                */
  16997.  /*                                                                  */
  16998.  /*                      Version: 3  Release: 1                      */
  16999.  /*                                                                  */
  17000.  /********************************************************************/
  17001.  
  17002. #ifdef SASC
  17003. #pragma  runopts(EXECOPS)
  17004. #else
  17005. #pragma  runopts(heap(8k,8k,anywhere,))
  17006. #pragma  runopts(nospie,nostae)
  17007. #endif
  17008.  
  17009. #pragma  csect(code,  "NN@MAIN ")
  17010. #pragma  csect(static,"NN$MAIN ")
  17011. #include "nn.h"
  17012.  
  17013. /*********************************************************************/
  17014.  
  17015. static char copyright_notice[] =
  17016.    "Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992   \n\
  17017.                                                                     \n\
  17018.     SAS enhancements copyright (c) 1992 SAS Institute, Inc.         \n\
  17019.                                                                     \n\
  17020.     This software is provided on an 'AS IS' basis.  All warranties, \n\
  17021.     including the implied warranties of merchantability and fitness,\n\
  17022.     are expressly denied.                                           \n\
  17023.                                                                     \n\
  17024.     Provided this copyright notice is included, this software may   \n\
  17025.     be freely distributed and not offered for sale.                 \n\
  17026.                                                                     \n\
  17027.     Changes or modifications may be made and used only by the maker \n\
  17028.     of same, and not further distributed.  Such modifications should\n\
  17029.     be mailed to the author for consideration for addition to the   \n\
  17030.     software and incorporation in subsequent releases.";
  17031.  
  17032. /*********************************************************************/
  17033.  
  17034. #ifdef I370
  17035. char * _style = "tso:";
  17036. #endif
  17037.  
  17038. /*********************************************************************/
  17039.  
  17040. static void
  17041. trap_ispf_command(np,verb,action)
  17042. Rstruc nncb      *np;
  17043. char             *verb;
  17044. char             *action;
  17045. {
  17046.  char             zcttrunc [16];
  17047.  char             zctact   [64];
  17048.  char             zctdesc [128];
  17049.  
  17050.  if (!NNMivput(np,"ZCTVERB ",verb,-1)) return;
  17051.  
  17052.  if (!NNMispf(np,"TBTOP ISPCMDS")) return;
  17053.  if (!NNMispf(np,"TBSCAN ISPCMDS ARGLIST(ZCTVERB)")) return;
  17054.  if (!NNMivget(np,"ZCTACT ",zctact,sizeof(zctact)))  return;
  17055.  if (UNEQUAL(zctact,action)) {
  17056.    NNMivget(np,"ZCTTRUNC ",zcttrunc, sizeof(zcttrunc));
  17057.    NNMivget(np,"ZCTDESC  ",zctdesc,sizeof(zctdesc));
  17058.    if (!NNMispf(np,"TBTOP ISPCMDS ")) return;
  17059.    NNMivput(np,"ZCTACT   ",action   ,-1);
  17060.    NNMivput(np,"ZCTTRUNC ",zcttrunc ,-1);
  17061.    NNMivput(np,"ZCTDESC  ",zctdesc  ,-1);
  17062.    if (!NNMispf(np,"TBADD ISPCMDS ")) return;
  17063.  }
  17064.  
  17065.  return; 
  17066. }
  17067.  
  17068. /*********************************************************************/
  17069.  
  17070. static Bool
  17071. alloc_newsrc(newsrc_dsname,newsrc_ddname)
  17072. char           *newsrc_dsname;
  17073. char           *newsrc_ddname;
  17074. {
  17075.  int            space;
  17076.  char          *lparp;
  17077.  char          *rparp;
  17078.  FILE          *mfile;
  17079.  char           dsnseq [81];
  17080.  char           member [81];
  17081.  char           what_to_open [81];
  17082.  
  17083.  space = 2;
  17084.  strcpy(member,"");
  17085.  strcpy(dsnseq,newsrc_dsname);
  17086.  lparp = strchr(dsnseq,'(');
  17087.  rparp = strchr(dsnseq,')');
  17088.  if (lparp && rparp && (lparp < rparp) && (*(rparp+1) == '\0')) {
  17089.    *lparp = '\0';            /* makes dsnseq the seq part only */
  17090.    *rparp = '\0';            /* turns member into a string     */
  17091.    strcpy(member, lparp+1);
  17092.    space = 10;
  17093.  }
  17094.  
  17095.  if (!NNMalloc(newsrc_dsname,newsrc_ddname,SEQ,space)) return FALSE;
  17096.  
  17097.  /* If the data set had a member specified, it may have been
  17098.   * allocated as NEW, or the member may not exist.  Therefore,
  17099.   * force the member to exist by opening it for output and closing
  17100.   * it if it doesn't exist.  Then reallocate it as an existing
  17101.   * data set to prevent a B14 abend when we try to write a new
  17102.   * PDS + member for output and close it.
  17103.   *
  17104.   * Otherwise, make sure the data set is not empty by opening it
  17105.   * in append mode - this also insures that it is writable.
  17106.   */
  17107.  
  17108. #ifdef SASC
  17109.  
  17110.  if (*member) {
  17111.    sprintf(what_to_open, "'%s(%s)'", dsnseq, member);
  17112.  
  17113.    /* SAS/C doesn't distinguish "member not found" from "file not
  17114.     * found".  He also likes to complain a lot.
  17115.     * -DDI
  17116.     */
  17117.  
  17118.    quiet(1);                         /* turn off stupid messages */
  17119.    mfile = fopen(what_to_open,"r");
  17120.    quiet(0);                         /* turn stupid messages back on */
  17121.    if (!mfile && errno == ENFOUND) {        /* Member not found */
  17122.      mfile = fopen(what_to_open,"w");   /* create new member */
  17123.    }
  17124.    if (!mfile) {
  17125.      perror(what_to_open);
  17126.      return FALSE;
  17127.    }
  17128.    else if (fclose(mfile) < 0) {
  17129.      fprintf(stderr, "Error closing %s\n", what_to_open);
  17130.      return FALSE;
  17131.    }
  17132.    (void)NNMunalc(newsrc_ddname);
  17133.    if (!NNMalloc(newsrc_dsname,newsrc_ddname,SEQ,0)) return FALSE;
  17134.  }
  17135.  else {
  17136.    sprintf(what_to_open, "dd:%s", newsrc_ddname);
  17137.  
  17138.    /* SAS/C treats an empty file as "non-existent", so we have to
  17139.     * write out a blank so that NNMonrf can later open it for input
  17140.     * successfully (even though nothing is there).  Bizarre, huh?
  17141.     * -DDI
  17142.     */
  17143.  
  17144.    quiet(1);                         /* turn off stupid messages */
  17145.    mfile = fopen(what_to_open,"r");  /* attempt to open for input */
  17146.    quiet(0);                         /* turn stupid messages back on */
  17147.    if (!mfile) {                     /* if open failed, must be empty */
  17148.      mfile = fopen(what_to_open,"w");/* so open for output */
  17149.      if (!mfile) {                   /* if that fails, give up */
  17150.        perror(what_to_open);
  17151.        return FALSE;
  17152.      }
  17153.      fputc(' ',mfile);               /* make it non-empty */
  17154.    }
  17155.    if (fclose(mfile) < 0) {          /* and close it either way */
  17156.      fprintf(stderr, "Error closing %s\n", what_to_open);
  17157.      return FALSE;
  17158.    }
  17159.  
  17160.  }
  17161.  
  17162. #else
  17163.  
  17164.  if (*member) {
  17165.    sprintf(what_to_open, "'%s(%s)'", dsnseq, member);
  17166.    mfile = fopen(what_to_open,"r");
  17167.    if (!mfile && errno == 104) {        /* Member not found */
  17168.      mfile = fopen(what_to_open,"w");   /* create new member */
  17169.    }
  17170.    if (!mfile) {
  17171.      perror(what_to_open);
  17172.      return FALSE;
  17173.    }
  17174.    else if (fclose(mfile) < 0) {
  17175.      fprintf(stderr, "Error closing %s\n", what_to_open);
  17176.      return FALSE;
  17177.    }
  17178.    (void)NNMunalc(newsrc_ddname);
  17179.    if (!NNMalloc(newsrc_dsname,newsrc_ddname,SEQ,0)) return FALSE;
  17180.  }
  17181.  else {
  17182.    sprintf(what_to_open, "dd:%s", newsrc_ddname);
  17183.    mfile = fopen(what_to_open,"a");
  17184.    if (!mfile) {
  17185.      perror(what_to_open);
  17186.      return FALSE;
  17187.    }
  17188.    else if (fclose(mfile) < 0) {
  17189.      fprintf(stderr, "Error closing %s\n", what_to_open);
  17190.      return FALSE;
  17191.    }
  17192.  }
  17193.  
  17194. #endif
  17195.  
  17196.  return TRUE;
  17197. }
  17198.  
  17199. /*********************************************************************/
  17200.  
  17201. int
  17202. main(argc,argv)
  17203. int      argc;
  17204. char   **argv;
  17205.  
  17206. {
  17207.  struct nncb            *np;
  17208.  char                   *p;
  17209.  Bool                  (*selection_processor)();
  17210.  struct hostent         *client_hp;
  17211.  int                     gethostnamerc;
  17212.  int                     exit_return_code;
  17213.  Bool                    display_continue;
  17214.  Bool                    ok_to_update_newsrc;
  17215.  struct nncb             nn;
  17216.  char                    newsrc_dsname  [65];
  17217.  
  17218.  exit_return_code = 0;
  17219.  
  17220.  memset(&nn,0,sizeof(struct nncb));
  17221.  
  17222.  np = &nn;
  17223.  
  17224.  np->test_mode  = FALSE;
  17225.  np->debug_mode = FALSE;
  17226.  np->batch_mode = FALSE;
  17227.  np->preselection = '\0';
  17228.  if (argc > 1) {
  17229.    p = argv[1];
  17230.    if (*p == '-') {
  17231.      while (*++p) {
  17232.        switch (toupper(*p)) {
  17233.          case 'T':  np->test_mode  = TRUE;    break;
  17234.          case 'D':  np->debug_mode = TRUE;    break;
  17235.          case 'B':  np->batch_mode = TRUE;    break;
  17236.          case SELECTION_ALL:
  17237.          case SELECTION_REG:
  17238.          case SELECTION_NNTP:
  17239.          case SELECTION_GROUP:
  17240.          case SELECTION_LIST:
  17241.          case SELECTION_NEWG:
  17242.          case SELECTION_OPTS:
  17243.          case SELECTION_EXIT:
  17244.                     np->preselection = *p;    break;
  17245.          default: fprintf(stderr,"NNMVS: Bad parameter flag %c\n", *p);
  17246.                   exit_return_code = 8;
  17247.        } 
  17248.      }
  17249.    }
  17250.    else {
  17251.      fprintf(stderr,"NNMVS: Bad parameter string %s\n",p);
  17252.      exit_return_code = 8;
  17253.    }
  17254.  }
  17255.  
  17256.  if (np->test_mode) __ctest(NULL);
  17257.  
  17258.  if (np->debug_mode) {
  17259.    if (!(np->debug_file = fopen("dd:nndebug","w"))) {
  17260.      perror("debug file (DD NNDEBUG)");
  17261.      exit_return_code = 4;
  17262.    }
  17263.  }
  17264.  else np->debug_file = NULL;
  17265.  
  17266.  if (np->batch_mode) {
  17267.    if (!(np->batch_infile = fopen("dd:NNBATIN","r"))) {
  17268.      perror("batch input file (dd:NNBATIN)");
  17269.    }
  17270.    if (!(np->batch_outfile = fopen("dd:NNBATOUT","w"))) {
  17271.      perror("batch output file (dd:NNBATOUT)");
  17272.    }
  17273.  }
  17274.  else {
  17275.    np->batch_infile  = NULL;
  17276.    np->batch_outfile = NULL;
  17277.  }
  17278.  
  17279.  /* This doesn't work, and may even make things worse.
  17280.   * if (signal(SIGINT,attention_handler) == SIG_ERR) {
  17281.   *   fprintf(stderr,"Error: unable to establish attention handler.\n");
  17282.   *   exit(27);
  17283.   * }
  17284.   */
  17285.  
  17286.  np->g_bytes_returned = 0;
  17287.  np->g_buf_index      = -1;
  17288.  
  17289.  /* Determine the local path name. */
  17290.  
  17291.  gethostnamerc = gethostname(np->client_hostname,MAXHOSTNAMELEN);
  17292.  if (gethostnamerc < 0) {
  17293.    fprintf(stderr,"NNMVS: gethostname() failed, don't know my name\n");
  17294.    exit_return_code = 8;
  17295.  }
  17296.  else {
  17297.    client_hp = gethostbyname(np->client_hostname);
  17298.    if (!client_hp) {
  17299.      fprintf(stderr,
  17300.              "NNMVS: gethostbyname() failed, can't get my name\n");
  17301.      exit_return_code = 8;
  17302.    }
  17303.    else {
  17304.      strcpy(np->nnclient,np->client_hostname);
  17305.      strcpy(np->client_hostname, client_hp->h_name);
  17306.      np->client_ip_address = *(IPADDRESS *)client_hp->h_addr;
  17307.    }
  17308.  }
  17309.  
  17310.  strcpy(np->nnserver,"");
  17311.  np->connected_to_server   = FALSE;
  17312.  np->closing_connection    = FALSE;
  17313.  np->reconnect_in_progress = FALSE;
  17314.  np->receiving_text        = FALSE;
  17315.  np->newsgroup_selected    = FALSE;
  17316.  
  17317.  GETMAIN(np->server_buf,   char, SERVER_BUF_MSGSIZE+4,"server buffer");
  17318.  GETMAIN(np->client_buf,   char, CLIENT_BUF_MSGSIZE+4,"client buffer");
  17319.  GETMAIN(np->nntp_command, char, CLIENT_BUF_MSGSIZE+4,"NNTP command");
  17320.  
  17321.  if (exit_return_code > 4) /* nothing */;
  17322.  else if (np->batch_mode) {
  17323.    exit_return_code = NNMbatch(np);
  17324.  }
  17325.  else {
  17326.  
  17327. #ifdef FETCH
  17328.  
  17329.    np->isplink_pointer = (int (*) ())fetch("ISPLINK");
  17330.    np->ispexec_pointer = (int (*) ())fetch("ISPEXEC");
  17331.  
  17332. #endif
  17333.  
  17334.    if (!NNMispf(np,"CONTROL ERRORS RETURN")) exit_return_code = 20;
  17335.  
  17336.    else {
  17337.  
  17338.      NNMinit(np);  /* Set up command and selection code tables */
  17339.  
  17340.      (void)NNMivput(np,"ZCMD "    ,"",-1);
  17341.      (void)NNMivput(np,"NNCURSOR ","",-1);
  17342.  
  17343.      trap_ispf_command(np,"RFIND","&YRFIND");  /* enable RFIND */
  17344.  
  17345.      NNMsopt(np,OPTION_ALL); /* Set options */
  17346.  
  17347.      strcpy(np->newsrc_to_open,"dd:");
  17348.  
  17349.      do {
  17350.        NNMunalc(np->newsrc_to_open+3);
  17351.        switch (NNMdmenu(np,&selection_processor)) {  /* Display menu */
  17352.          case DISPLAY_REPEAT:
  17353.          case DISPLAY_ERROR:   display_continue = TRUE;  break;
  17354.          case DISPLAY_EXIT:
  17355.          case DISPLAY_FAILURE: display_continue = FALSE; break;
  17356.        } 
  17357.        if (display_continue
  17358.         && selection_processor
  17359.         && NNMivget(np,"NNNEWSRC ",newsrc_dsname,sizeof(newsrc_dsname))
  17360.         && alloc_newsrc(newsrc_dsname,np->newsrc_to_open+3)) {
  17361.          NNMclrng(np);                          /* Clear newsgroups */
  17362.          NNMclrtx(np,NULL);                     /* Clear text       */
  17363.          NNMonrf(np,NULL);                      /* Open NEWSRC file */
  17364.          (void)NNMivput(np,"ZCMD ","",-1);      /* Clear ZCMD field */
  17365.  
  17366.          /* Call selected function. If returns TRUE, rewrite NEWSRC */
  17367.  
  17368.          ok_to_update_newsrc = (*selection_processor)(np);
  17369.          NNMcnrf(np,NULL,
  17370.                  ok_to_update_newsrc); /* Close/rewrite NEWSRC file */
  17371.        } 
  17372.      } while (display_continue && !np->quit);
  17373.  
  17374.      exit_return_code = 0;
  17375.  
  17376.    }
  17377.  
  17378.  }
  17379.  
  17380.  if (*np->maildsn) {
  17381.    if (remove(np->maildsn) < 0) {
  17382.      fprintf(stderr,"NNMVS: Error removing mail dataset %s\n");
  17383.    }
  17384.  }
  17385.  
  17386.  if (np->connected_to_server) {
  17387.    NNMdisc(np);                 /* disconnect from news server */
  17388.  }
  17389.  
  17390.  NNMclrng(np);                  /* Clear newsgroups */
  17391.  
  17392.  FREEMAIN(np->nntp_command,"nntp command");
  17393.  FREEMAIN(np->server_buf,  "server buffer");
  17394.  FREEMAIN(np->client_buf,  "client buffer");
  17395.  
  17396.  #define FINAL_CLOSE(A,B) \
  17397.    if (A) { \
  17398.             if (fclose(A) < 0) fprintf(stderr,B); \
  17399.           }
  17400.  
  17401.  FINAL_CLOSE(np->newsrc_file   , "Error closing newsrc file\n");
  17402.  FINAL_CLOSE(np->debug_file    , "Error closing debug file\n");
  17403.  FINAL_CLOSE(np->batch_infile  , "Error closing batch input file\n");
  17404.  FINAL_CLOSE(np->batch_outfile , "Error closing batch output file\n");
  17405.  
  17406.  exit(exit_return_code);
  17407. }
  17408.  
  17409. ./   ADD NAME=NNMMARR,SSI=01030019
  17410.  
  17411.  /********************************************************************/
  17412.  /*                                                                  */
  17413.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  17414.  /*                                                                  */
  17415.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  17416.  /* including the implied warranties of merchantability and fitness, */
  17417.  /* are expressly denied.                                            */
  17418.  /*                                                                  */
  17419.  /* Provided this copyright notice is included, this software may    */
  17420.  /* be freely distributed and not offered for sale.                  */
  17421.  /*                                                                  */
  17422.  /* Changes or modifications may be made and used only by the maker  */
  17423.  /* of same, and not further distributed.  Such modifications should */
  17424.  /* be mailed to the author for consideration for addition to the    */
  17425.  /* software and incorporation in subsequent releases.               */
  17426.  /*                                                                  */
  17427.  /********************************************************************/
  17428.  
  17429. #pragma  csect(code,  "NN@MARR ")
  17430. #pragma  csect(static,"NN$MARR ")
  17431. #include "nn.h"
  17432.  
  17433. /****** Make article read. *******************************************/
  17434.  
  17435. void
  17436. NNMmarr(np,gp,vp)
  17437. Rstruc nncb         *np;
  17438. Rstruc newsgroup    *gp;
  17439. register VARK       *vp;
  17440. {
  17441.  struct newsarticle *ap;
  17442.  
  17443.  if (IsUnread(*vp)) {
  17444.    SetRead(*vp);
  17445.    gp->unread_count--;
  17446.  }
  17447.  
  17448.  if (!IsNull(*vp) && !IsMissing(*vp)) {
  17449.    ap = VARK2PARTICLE(*vp);
  17450.    ap->action = READ;
  17451.  }
  17452.  
  17453.  return; 
  17454. }
  17455.  
  17456. ./   ADD NAME=NNMMARU,SSI=01010050
  17457.  
  17458.  /********************************************************************/
  17459.  /*                                                                  */
  17460.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  17461.  /*                                                                  */
  17462.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  17463.  /* including the implied warranties of merchantability and fitness, */
  17464.  /* are expressly denied.                                            */
  17465.  /*                                                                  */
  17466.  /* Provided this copyright notice is included, this software may    */
  17467.  /* be freely distributed and not offered for sale.                  */
  17468.  /*                                                                  */
  17469.  /* Changes or modifications may be made and used only by the maker  */
  17470.  /* of same, and not further distributed.  Such modifications should */
  17471.  /* be mailed to the author for consideration for addition to the    */
  17472.  /* software and incorporation in subsequent releases.               */
  17473.  /*                                                                  */
  17474.  /********************************************************************/
  17475.  
  17476. #pragma  csect(code,  "NN@MARU ")
  17477. #pragma  csect(static,"NN$MARU ")
  17478. #include "nn.h"
  17479.  
  17480. /****** Make article unread. *****************************************/
  17481.  
  17482. void
  17483. NNMmaru(np,gp,vp)
  17484. Rstruc nncb         *np;
  17485. Rstruc newsgroup    *gp;
  17486. register VARK       *vp;
  17487. {
  17488.  struct newsarticle *ap;
  17489.  
  17490.  if (IsRead(*vp)) {
  17491.    SetUnread(*vp);
  17492.    gp->unread_count++;
  17493.  }
  17494.  
  17495.  if (!IsNull(*vp) && !IsMissing(*vp)) {
  17496.    ap = VARK2PARTICLE(*vp);
  17497.    ap->action = UNREAD;
  17498.  }
  17499.  
  17500.  return; 
  17501. }
  17502.  
  17503. ./   ADD NAME=NNMNNTP,SSI=01070007
  17504.  
  17505.  /********************************************************************/
  17506.  /*                                                                  */
  17507.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  17508.  /*                                                                  */
  17509.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  17510.  /* including the implied warranties of merchantability and fitness, */
  17511.  /* are expressly denied.                                            */
  17512.  /*                                                                  */
  17513.  /* Provided this copyright notice is included, this software may    */
  17514.  /* be freely distributed and not offered for sale.                  */
  17515.  /*                                                                  */
  17516.  /* Changes or modifications may be made and used only by the maker  */
  17517.  /* of same, and not further distributed.  Such modifications should */
  17518.  /* be mailed to the author for consideration for addition to the    */
  17519.  /* software and incorporation in subsequent releases.               */
  17520.  /*                                                                  */
  17521.  /********************************************************************/
  17522.  
  17523. #pragma  csect(code,  "NN@NNTP ")
  17524. #pragma  csect(static,"NN$NNTP ")
  17525. #include "nn.h"
  17526.  
  17527. /****** Read server data. ********************************************/
  17528.  
  17529. static Bool
  17530. read_server_data(np)
  17531. Rstruc nncb         *np;
  17532. {
  17533.  char               *lp;
  17534.  
  17535.  NNMclrtx(np,NULL);                   /* Clear text */
  17536.  
  17537.  do {
  17538.  
  17539.    if (NNMgsrvl(np,&lp))              /* Get server line */
  17540.      if (lp) {
  17541.        (void)NNMouttx(np,lp,NULL);   /* Output text line */
  17542.      }
  17543.  
  17544.  } while (lp);
  17545.  
  17546.  if (np->time_to_go_home) return FALSE;
  17547.  else return TRUE;
  17548. }
  17549.  
  17550. /************ Execute native NNTP protocol commands. *****************/
  17551.  
  17552. void
  17553. NNMnntp(np)
  17554. Rstruc nncb *np;
  17555. {
  17556.  struct texthdr   saveth;
  17557.  
  17558.  /* np->nntp_command must contain NNTP command */
  17559.  
  17560.  if (!np->receiving_text && !*np->nntp_command) return;
  17561.  
  17562.  np->newsgroup_selected = FALSE;  /* in case we change server's state
  17563.                                      with a command like "GROUP xxx" */
  17564.  
  17565.  memcpy(&saveth,&np->thdr,sizeof(struct texthdr));
  17566.  memset(&np->thdr,0,sizeof(struct texthdr));
  17567.  
  17568.  if (NNMsockt(np)) {              /* Send socket command to server */
  17569.    if (read_server_data(np,NULL)) {           /* Read server data */
  17570.      NNMvtx(np,NULL,NULL);                    /* View text        */
  17571.    }
  17572.    NNMclrtx(np,NULL);
  17573.  }
  17574.  memcpy(&np->thdr,&saveth,sizeof(struct texthdr));
  17575.  return; 
  17576. }
  17577.  
  17578. ./   ADD NAME=NNMONRF,SSI=01020041
  17579.  
  17580.  /********************************************************************/
  17581.  /*                                                                  */
  17582.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  17583.  /*                                                                  */
  17584.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  17585.  /*                                                                  */
  17586.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  17587.  /* including the implied warranties of merchantability and fitness, */
  17588.  /* are expressly denied.                                            */
  17589.  /*                                                                  */
  17590.  /* Provided this copyright notice is included, this software may    */
  17591.  /* be freely distributed and not offered for sale.                  */
  17592.  /*                                                                  */
  17593.  /* Changes or modifications may be made and used only by the maker  */
  17594.  /* of same, and not further distributed.  Such modifications should */
  17595.  /* be mailed to the author for consideration for addition to the    */
  17596.  /* software and incorporation in subsequent releases.               */
  17597.  /*                                                                  */
  17598.  /********************************************************************/
  17599.  
  17600. #pragma  csect(code,  "NN@ONRF ")
  17601. #pragma  csect(static,"NN$ONRF ")
  17602. #include "nn.h"
  17603.  
  17604. /****** Open NEWSRC file. ********************************************/
  17605.  
  17606. void
  17607. NNMonrf(np,what_to_open)
  17608. Rstruc nncb         *np;
  17609. char                *what_to_open;
  17610. {
  17611.  char                newsrc_line[256];
  17612.  char                newsrc_name[GROUP_NAME_SIZE];
  17613.  Rstruc newsgroup   *gp;
  17614.  register char      *nlp;
  17615.  char               *temp;
  17616.  int                 sscanf_rc;
  17617.  int                 newsrc_registered;
  17618.  int                 newsrc_unread;
  17619.  int                 newsrc_topnum;
  17620.  int                 newsrc_scan_count;
  17621.  int                 newsrc_save_length;
  17622.  
  17623.  if (!what_to_open) what_to_open = np->newsrc_to_open;
  17624.  
  17625.  /* If the file does not exist, then create it. */
  17626.  
  17627.  newsrc_scan_count = 0;
  17628.  np->brand_new_newsrc = TRUE;
  17629.  
  17630.  errno = 0;
  17631.  
  17632.  if (!(np->newsrc_file = fopen(what_to_open,"r"))) {
  17633.    if (errno == 104) {  /* Member not found */
  17634.      if (!(np->newsrc_file = fopen(what_to_open,"w"))) {
  17635.        perror("Cannot create NEWSRC PDS member");
  17636.      }
  17637.      else if (fclose(np->newsrc_file) < 0) {
  17638.        fprintf(stderr, "Error closing %s\n", what_to_open);
  17639.        np->newsrc_file = NULL;
  17640.      }
  17641.      else np->newsrc_file = fopen(what_to_open,"r");
  17642.    }
  17643.    else perror("Cannot open NEWSRC file");
  17644.  }
  17645.  if (!np->newsrc_file) {
  17646.    fprintf(stderr,"Severe error, NEWSRC file cannot be opened.\n");
  17647.    if (!np->batch_mode) {
  17648.      (void)NNMdispl(np,"NNMRCERR");
  17649.    }
  17650.    exit(12);
  17651.  }
  17652.  
  17653.  np->new_newsgroup_count = 0;
  17654.  
  17655.  /* Read from the file, saving the state information. */
  17656.  
  17657.  /********************************************************************/
  17658.  /*                                                                  */
  17659.  /* Note:  The format used here is designed to be compatible with    */
  17660.  /*        the format used by ANU-NEWS.  This is not an attempt to   */
  17661.  /*        duplicate the "look and feel" of ANU-NEWS - it is just    */
  17662.  /*        to be compatible with the saved state of VAX NEWS users.  */
  17663.  /*                                                                  */
  17664.  /********************************************************************/
  17665.  
  17666.  if (feof(np->newsrc_file)) return;
  17667.  
  17668.  /* First line: time in hex digits of last "registration", and some
  17669.   * other junk.  We now interpret this as the last time the status
  17670.   * of the server's newsgroups was interrogated (LIST or NEWGROUPS)
  17671.   * and save it.
  17672.   */
  17673.  
  17674.  fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  17675.  if (strlen(newsrc_line) >= 13)      /* if new format .newsrc file  */
  17676.     sscanf(newsrc_line, "%6c %6c", &np->lastNGdate, &np->lastNGtime);
  17677.  
  17678.  if (feof(np->newsrc_file)) return;
  17679.  
  17680.  /* The rest of the file consists of information about newsgroups.
  17681.     Read until end of file or one of the special markers is found. */
  17682.  
  17683.  fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  17684.  
  17685.  while (!feof(np->newsrc_file)) {
  17686.  
  17687.    if (EQUAL(newsrc_line,"MARKLIST\n"))  break;
  17688.    if (EQUAL(newsrc_line,"KILLLIST\n"))  break;
  17689.    if (EQUAL(newsrc_line,"PROFILE\n"))   break;
  17690.  
  17691.  /* For each line, build a newsgroup entry and fill it in with
  17692.     the values taken from the input line. */
  17693.  
  17694.  /* Right now we are not checking for {classname,classname} as we
  17695.     don't know how, and it would complicate things. */
  17696.  
  17697.    nlp = strchr(newsrc_line,':');
  17698.    if (!nlp) nlp = strchr(newsrc_line,'\n');
  17699.    if (!nlp) {
  17700.      fprintf(stderr,"Bad name in newsrc file, ignored:\n%s\n\n",
  17701.                     newsrc_line);
  17702.      fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  17703.      continue;
  17704.    }
  17705.    memcpy(newsrc_name,newsrc_line,nlp-newsrc_line);
  17706.    newsrc_name[nlp-newsrc_line] = '\0';
  17707.    if (*nlp == '\n' || *(nlp+1) == '\n') sscanf_rc = 0;
  17708.    else
  17709.     sscanf_rc = sscanf(nlp,": (%d) [%d,%d] %n",
  17710.                              &newsrc_registered,
  17711.                              &newsrc_unread,
  17712.                              &newsrc_topnum,
  17713.                              &newsrc_scan_count);
  17714.  
  17715.    switch (sscanf_rc) {    /* Note use of switch WITHOUT break here. */
  17716.       case EOF: newsrc_registered = 1;
  17717.       case 0:   newsrc_registered = 1;
  17718.       case 1:   newsrc_unread     = 0;
  17719.       case 2:   newsrc_topnum     = 0;
  17720.                 nlp = NULL;
  17721.       case 3:   break;
  17722.       default:  break;
  17723.    }
  17724.  
  17725.    np->brand_new_newsrc = FALSE;
  17726.  
  17727.    /* Allocate a newsgroup for this record. */
  17728.  
  17729.    gp = NNMaddng(np,newsrc_name);     /* Add newsgroup */
  17730.    if (!gp) {
  17731.       fprintf(stderr,"Cannot initialize newsgroup: %s\n",newsrc_name);
  17732.       fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  17733.       continue;
  17734.    }
  17735.  
  17736.    /* Now, collect the information on what articles were read. */
  17737.  
  17738.    SetGroupFromNewsrc(gp);
  17739.    gp->low_number    = 1;             /* or new field from newsrc? */
  17740.    gp->high_number   = newsrc_topnum;
  17741.    gp->vector_first  = 0;
  17742.    gp->vector_last   = 0;
  17743.    gp->article_count = gp->high_number - gp->low_number + 1;
  17744.    gp->unread_count  = newsrc_unread;
  17745.    gp->registered    = newsrc_registered;
  17746.  
  17747.    if (gp->registered == -1) {
  17748.      SetNewGroup(gp);
  17749.      gp->registered = 0;
  17750.      np->new_newsgroup_count++;
  17751.    }
  17752.  
  17753.    /* At this early point, we just save the NEWSRC line and
  17754.     * create the article vector later, when we really need it.
  17755.     */
  17756.  
  17757.    if (!nlp) {
  17758.      fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  17759.      continue;
  17760.    }
  17761.  
  17762.    nlp += newsrc_scan_count;
  17763.  
  17764.    /* Save the newsrc data (following the [unread,topnum] spec) */
  17765.  
  17766.    if (gp->saved_newsrc_line != gp->saved_newsrc_data) {
  17767.      FREEMAIN(gp->saved_newsrc_line,"stale saved newsrc line");
  17768.    }
  17769.    if (*nlp == '\0') nlp = "\n";
  17770.    newsrc_save_length = strlen(nlp) + 1;
  17771.    if (newsrc_save_length <= sizeof(gp->saved_newsrc_data)) {
  17772.      gp->saved_newsrc_line = gp->saved_newsrc_data;
  17773.    }
  17774.    else {
  17775.      GETMAIN(gp->saved_newsrc_line,char,newsrc_save_length,
  17776.              "saved newsrc line");
  17777.      if (!gp->saved_newsrc_line) {
  17778.        fprintf(stderr,"Cannot save newsrc line for %s, terminating.\n",
  17779.                       newsrc_name);
  17780.        return;
  17781.      }
  17782.    }
  17783.    strcpy(gp->saved_newsrc_line,nlp);
  17784.  
  17785.    for (;;) {
  17786.  
  17787.      fgets(newsrc_line,sizeof(newsrc_line),np->newsrc_file);
  17788.      if (feof(np->newsrc_file)) break;
  17789.      if (newsrc_line[0] != ' ') break;
  17790.      nlp = newsrc_line;
  17791.      GETMAIN(temp,char,strlen(gp->saved_newsrc_line)+strlen(nlp)+1,
  17792.                        "saved newsrc line continuation");
  17793.      if (!temp) {
  17794.        fprintf(stderr,"Cannot save newsrc line for %s, terminating.\n",
  17795.                       newsrc_name);
  17796.        return;
  17797.      }
  17798.      strcpy(temp,gp->saved_newsrc_line);  /* should include newline */
  17799.      strcat(temp,nlp);
  17800.      if (gp->saved_newsrc_line != gp->saved_newsrc_data) {
  17801.        FREEMAIN(gp->saved_newsrc_line,"old saved newsrc line");
  17802.      }
  17803.      gp->saved_newsrc_line = temp;
  17804.  
  17805.    } /* end for - at this point we have no more newsrc continuations */
  17806.  
  17807.  } /* end while */
  17808.  
  17809.  /* At this point we have finished reading newsrc.
  17810.     Ignore everything once MARKLIST, KILLLIST, or PROFILE is seen.
  17811.     We don't handle any of that stuff. */
  17812.  
  17813.  return; 
  17814. }
  17815.  
  17816. ./   ADD NAME=NNMOUTTX,SSI=01020023
  17817.  
  17818.  /********************************************************************/
  17819.  /*                                                                  */
  17820.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  17821.  /*                                                                  */
  17822.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  17823.  /* including the implied warranties of merchantability and fitness, */
  17824.  /* are expressly denied.                                            */
  17825.  /*                                                                  */
  17826.  /* Provided this copyright notice is included, this software may    */
  17827.  /* be freely distributed and not offered for sale.                  */
  17828.  /*                                                                  */
  17829.  /* Changes or modifications may be made and used only by the maker  */
  17830.  /* of same, and not further distributed.  Such modifications should */
  17831.  /* be mailed to the author for consideration for addition to the    */
  17832.  /* software and incorporation in subsequent releases.               */
  17833.  /*                                                                  */
  17834.  /********************************************************************/
  17835.  
  17836. #pragma  csect(code,  "NN@OUTTX")
  17837. #pragma  csect(static,"NN$OUTTX")
  17838. #include "nn.h"
  17839.  
  17840. /****** Output a line of text retrieved from the server. *************/
  17841.  
  17842. struct textline *
  17843. NNMouttx(np,line,ap)
  17844. Rstruc nncb         *np;
  17845. char                *line;
  17846. Rstruc newsarticle  *ap;
  17847.  
  17848. {
  17849.  struct texthdr     *thp;
  17850.  struct textline    *tp;
  17851.  short              line_length;
  17852.  short              total_text_length;
  17853.  short              tab_expansion_length;
  17854.  Bool               tabs_present;
  17855.  char              *p;
  17856.  char              *q;
  17857.  char              *t;
  17858.  int                e;
  17859.  int                u;
  17860.  
  17861.  static char        tab_expansion_buffer[8*TEXT_BYTES];
  17862.  
  17863.  /* If article is not specified, use main nncb, else article's text */
  17864.  
  17865.  thp = (ap ? &ap->thdr : &np->thdr);
  17866.  
  17867.  /* If line starts with double period, make it a single period. */
  17868.  
  17869.  if (ap && memcmp(line,"..",2) == 0) line++;
  17870.  
  17871.  /* Add this line to the current queue of server text lines. */
  17872.  
  17873.  /* First, expand tabs in the line. */
  17874.  
  17875.  line_length = strlen(line);
  17876.  t = strchr(line,'\t');
  17877.  if (!t) {
  17878.    tabs_present = FALSE;
  17879.    total_text_length = line_length + 1;
  17880.  }
  17881.  else {                                   /* expand tabs */
  17882.    tabs_present = TRUE;
  17883.    p = line;
  17884.    q = line + line_length;
  17885.    e = 0;
  17886.    memset(tab_expansion_buffer,' ',sizeof(tab_expansion_buffer));
  17887.    for (;;) {
  17888.      u = t - p;
  17889.      if (u > 0) {
  17890.        memcpy(tab_expansion_buffer+e,p,u);
  17891.        e += u;
  17892.      }
  17893.      if (t == q) break;
  17894.      e = e / 8 * 8 + 8;
  17895.      p = t+1;
  17896.      t = strchr(p,'\t');
  17897.      if (!t) t = q;
  17898.    }
  17899.    tab_expansion_length = e;
  17900.    tab_expansion_buffer[tab_expansion_length] = '\0';
  17901.    total_text_length = line_length + tab_expansion_length + 1;
  17902.  }
  17903.  
  17904.  GETMAIN(tp, char, offsetof(struct textline, text) + total_text_length,
  17905.                    "text line");
  17906.  
  17907.  if (!tp) {
  17908.    ERR1("There is not enough virtual storage to process server text.");
  17909.    return NULL;
  17910.  }
  17911.  
  17912.  tp->next = NULL;
  17913.  tp->text_length = line_length;
  17914.  strcpy(tp->text,line);
  17915.  if (tabs_present) {
  17916.    tp->tab_expanded_text_length = tab_expansion_length;
  17917.    tp->tab_expanded_text = tp->text + line_length;
  17918.    strcpy(tp->tab_expanded_text,tab_expansion_buffer);
  17919.  }
  17920.  else {
  17921.    tp->tab_expanded_text_length = line_length;
  17922.    tp->tab_expanded_text = tp->text;
  17923.  }
  17924.  
  17925.  if (!thp->last_text_line) {
  17926.    thp->first_text_line   = tp;
  17927.    thp->text_body_line    = tp;
  17928.    thp->current_text_line = tp;
  17929.  }
  17930.  else thp->last_text_line->next = tp;
  17931.  
  17932.  thp->last_text_line = tp;
  17933.  thp->text_line_count++;
  17934.  
  17935.  if (thp->text_max_length < tp->text_length)
  17936.      thp->text_max_length = tp->text_length;
  17937.  if (thp->text_max_tab_expanded_length < tp->tab_expanded_text_length)
  17938.      thp->text_max_tab_expanded_length = tp->tab_expanded_text_length;
  17939.  
  17940.  return tp;
  17941.  
  17942. }
  17943.  
  17944. ./   ADD NAME=NNMPICK,SSI=01040058
  17945.  
  17946.  /********************************************************************/
  17947.  /*                                                                  */
  17948.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  17949.  /*                                                                  */
  17950.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  17951.  /*                                                                  */
  17952.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  17953.  /* including the implied warranties of merchantability and fitness, */
  17954.  /* are expressly denied.                                            */
  17955.  /*                                                                  */
  17956.  /* Provided this copyright notice is included, this software may    */
  17957.  /* be freely distributed and not offered for sale.                  */
  17958.  /*                                                                  */
  17959.  /* Changes or modifications may be made and used only by the maker  */
  17960.  /* of same, and not further distributed.  Such modifications should */
  17961.  /* be mailed to the author for consideration for addition to the    */
  17962.  /* software and incorporation in subsequent releases.               */
  17963.  /*                                                                  */
  17964.  /********************************************************************/
  17965.  
  17966. #pragma  csect(code,  "NN@PICK ")
  17967. #pragma  csect(static,"NN$PICK ")
  17968. #include "nn.h"
  17969.  
  17970. /****** Collect text. ************************************************/
  17971.  
  17972. static void
  17973. collect_text(np,ap)
  17974. Rstruc nncb         *np;
  17975. Rstruc newsarticle  *ap;
  17976. {
  17977.  char               *lp;
  17978.  
  17979.  np->sending_text = TRUE;
  17980.  
  17981.  for (;;) {
  17982.  
  17983.    if (!NNMgsrvl(np,&lp))         break; /* Get server line */
  17984.    if (lp == NULL)                break;
  17985.    if (strcmp(lp,".") == 0)       break;
  17986.    if (!NNMouttx(np,lp,ap))       break; /* Output text line */
  17987.  
  17988.  }
  17989.  
  17990.  return; 
  17991.  
  17992. }
  17993.  
  17994. /****** Maybe suppress header line. **********************************/
  17995.  
  17996. static void
  17997. maybe_suppress_header_line(np,ap,tp,header_name)
  17998. Rstruc nncb         *np;
  17999. Rstruc newsarticle  *ap;
  18000. Rstruc textline     *tp;
  18001. char                *header_name;
  18002. {
  18003.  char                temphdr[INTERNET_SIZE+2];
  18004.  Bool                suppress;
  18005.  
  18006.  switch (np->nnrfcopt[0]) {
  18007.    case '\0':
  18008.    case 'A':                /* show all RFC822 headers */
  18009.               suppress = FALSE;
  18010.               break;
  18011.    case 'B':                /* show all except those in exclude list */
  18012.               sprintf(temphdr," %s ",header_name);
  18013.               if (strstr(np->nnrfcexc,temphdr)) suppress = TRUE;
  18014.               else                              suppress = FALSE;
  18015.               break;
  18016.    case 'C':                /* show only those in include list */
  18017.               sprintf(temphdr," %s ",header_name);
  18018.               if (strstr(np->nnrfcinc,temphdr)) suppress = FALSE;
  18019.               else                              suppress = TRUE;
  18020.               break;
  18021.    case 'D':                /* show none */
  18022.               suppress = TRUE;
  18023.               break;
  18024.  }
  18025.  
  18026.  if (suppress) {
  18027.    if (tp->text_length >= 0) {
  18028.      tp->text_length |= 0x8000;    /* force sign bit negative */
  18029.      ap->thdr.text_line_count--;
  18030.    }
  18031.  }
  18032.  else {
  18033.    if (tp->text_length < 0) {
  18034.      tp->text_length &= 0x7fff;    /* force sign bit positive */
  18035.      ap->thdr.text_line_count++;
  18036.    }
  18037.  }
  18038.  
  18039.  return; 
  18040. }
  18041.  
  18042. /****** Apply header suppression.  ***********************************/
  18043.  
  18044. static void
  18045. apply_header_suppression(np,ap)
  18046. Rstruc nncb         *np;
  18047. Rstruc newsarticle  *ap;
  18048. {
  18049.  struct textline     *tp;
  18050.  struct texthdr      *thp;
  18051.  char                *cp;
  18052.  char                *colonp;
  18053.  int                  header_index;
  18054.  char                 header_name[INTERNET_SIZE];
  18055.  
  18056.  thp = &ap->thdr;
  18057.  strcpy(header_name,"");
  18058.  for (tp=thp->first_text_line; tp; tp=tp->next) {
  18059.    if (tp->text[0] == '\0') break;
  18060.    if (tp->text[0] == ' ' ||
  18061.        tp->text[0] == '\t') {
  18062.      cp = tp->text + strspn(tp->text," \t");
  18063.      if (*cp == '\0') break;
  18064.    }
  18065.    else {
  18066.      header_index = 0;
  18067.      colonp = strchr(tp->text,':');
  18068.      if (!colonp) break;
  18069.      strcpy(header_name,"");
  18070.      for (cp = tp->text;cp<colonp;cp++) {
  18071.        header_name[header_index++] = toupper(*cp);
  18072.      }
  18073.      header_name[header_index] = '\0';
  18074.    }
  18075.    if (*header_name) {
  18076.       maybe_suppress_header_line(np,ap,tp,header_name);
  18077.    }
  18078.  }
  18079.  
  18080.  thp->text_body_line = tp;
  18081.  
  18082.  return; 
  18083. }
  18084.  
  18085. /****** Pick article before processing. ******************************/
  18086.  
  18087. Bool
  18088. NNMpick(np,ap)
  18089. Rstruc nncb          *np;
  18090. Rstruc newsarticle   *ap;
  18091. {
  18092.  Rstruc newsgroup    *gp;
  18093.  char                *lp;
  18094.  char                 bad_status        = ERROR;
  18095.  Bool                 retval            = TRUE;
  18096.  Bool                 retrieve_header   = FALSE;
  18097.  Bool                 retrieve_body     = FALSE;
  18098.  
  18099.  np->another_article = NULL_ARTICLE_COOKIE;
  18100.  
  18101.  gp = np->current_newsgroup;
  18102.  
  18103.  if (!gp) {
  18104.    CRIT1("No current newsgroup.  This should never happen.");
  18105.    return FALSE;
  18106.  }
  18107.  
  18108.  if (ap == V_NULL_ARTICLE) {
  18109.    ERR1("This article does not exist - how could it be chosen?");
  18110.    return FALSE;
  18111.  }
  18112.  
  18113.  if (ap == V_MISSING_ARTICLE) {
  18114.    ERR1("This article is missing - how could it be chosen?");
  18115.    return FALSE;
  18116.  }
  18117.  
  18118.  if (NoSuchArticle(ap)) {
  18119.    ERR4("Article %d of %s does not exist in server %s.",
  18120.         ap->number, gp->name, np->nnserver);
  18121.    retval = FALSE;
  18122.  }
  18123.  else if (ArticleAbsent(ap)) {
  18124.    ERR4("Article %d of %s was not retrieved by server %s.",
  18125.         ap->number, gp->name, np->nnserver);
  18126.    retval = FALSE;
  18127.  }
  18128.  else if (ArticleError(ap)) {
  18129.    ERR4("Error getting article %d of %s from server %s.",
  18130.         ap->number, gp->name, np->nnserver);
  18131.    retval = FALSE;
  18132.  }
  18133.  else {
  18134.    retrieve_header = !ArticleHeadRetrieved(ap);
  18135.    retrieve_body   = !ArticleBodyRetrieved(ap);
  18136.  }
  18137.  
  18138.  if (retrieve_header || retrieve_body) {
  18139.  
  18140.    if (!NNMestng(np,NULL)) {           /* Establish newsgroup */
  18141.      SetGroupError(gp);
  18142.      OffGroupSelected(gp);
  18143.      return FALSE;
  18144.    }
  18145.  
  18146.    if (retrieve_header) {
  18147.      if (!NNMrarh(np,gp,NULL,ap->number,NULL)) {
  18148.        ERR4("Article %d of %s could not be retrieved from server %s.",
  18149.             ap->number, gp->name, np->nnserver);
  18150.        ap->action = MISSING;
  18151.        return FALSE;
  18152.      }
  18153.    }
  18154.  
  18155.    sprintf(np->nntp_command,"BODY %d",ap->number);
  18156.    if (!NNMsockt(np))      return FALSE; /* Send socket cmd to server*/
  18157.    if (!NNMgsrvl(np,&lp))  return FALSE; /* Get server line */
  18158.    switch(np->nntp_message_num) {
  18159.      case 220:       /* article retrieved - head and body follow    */
  18160.                break;
  18161.      case 221:       /* article retrieved - head follows            */
  18162.                break;
  18163.      case 222:       /* article retrieved - body follows            */
  18164.                break;
  18165.      case 423:       /* no such article number in this group        */
  18166.                ERR4("Article %d of %s is missing from server %s.",
  18167.                     ap->number, gp->name, np->nnserver);
  18168.                bad_status = MISSING;
  18169.                retval = FALSE;
  18170.                break;
  18171.      case 430:       /* no such article found                       */
  18172.                ERR4("Article %d of %s could not be found by server %s.",
  18173.                     ap->number, gp->name, np->nnserver);
  18174.                bad_status = MISSING;
  18175.                retval = FALSE;
  18176.                break;
  18177.      case 223:       /* article retrieved - request text separately */
  18178.      case 412:       /* no newsgroup has been selected              */
  18179.      case 420:       /* no current article has been selected        */
  18180.      default:  NNMrperr(np);      /* Report protocol error */
  18181.                retval = FALSE;
  18182.                break;
  18183.    }
  18184.  }
  18185.  
  18186.  if (retval == FALSE) {
  18187.    ap->action = bad_status;
  18188.    return FALSE;
  18189.  }
  18190.  
  18191.  SetArticleRetrieved(ap);
  18192.  ap->action = NO_ACTION;
  18193.  
  18194.  if (retrieve_body) {
  18195.    if (!NNMouttx(np," ",ap)) return FALSE;    /* output text line */
  18196.    collect_text(np,ap);
  18197.  }
  18198.  
  18199.  apply_header_suppression(np,ap);
  18200.  
  18201.  return TRUE;
  18202. }
  18203.  
  18204. ./   ADD NAME=NNMPMSG,SSI=01040049
  18205.  
  18206.  /********************************************************************/
  18207.  /*                                                                  */
  18208.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  18209.  /*                                                                  */
  18210.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  18211.  /* including the implied warranties of merchantability and fitness, */
  18212.  /* are expressly denied.                                            */
  18213.  /*                                                                  */
  18214.  /* Provided this copyright notice is included, this software may    */
  18215.  /* be freely distributed and not offered for sale.                  */
  18216.  /*                                                                  */
  18217.  /* Changes or modifications may be made and used only by the maker  */
  18218.  /* of same, and not further distributed.  Such modifications should */
  18219.  /* be mailed to the author for consideration for addition to the    */
  18220.  /* software and incorporation in subsequent releases.               */
  18221.  /*                                                                  */
  18222.  /********************************************************************/
  18223.  
  18224. #define  SUPPRESS_V_DECLARATION
  18225. #pragma  csect(code,  "NN@PMSG ")
  18226. #pragma  csect(static,"NN$PMSG ")
  18227. #include "nn.h"
  18228.  
  18229. /****** Set an ISPF message, or write to SYSOUT if batch mode. *******/
  18230.  
  18231. void
  18232. NNMpmsg(np,msgtype,msghelp,msgformat) /* also ... for sprintf args */
  18233. Rstruc nncb *np;
  18234. int          msgtype;
  18235. char        *msghelp;
  18236. char        *msgformat;
  18237. {
  18238.  va_list     argp;
  18239.  char       *cp;
  18240.  char        zerrsm    [25];
  18241.  char        zerrhm     [9];
  18242.  char        zerralrm   [4];
  18243.  char        zerrlm   [ZERRLM_SIZE];
  18244.  char        buf      [257];
  18245.  
  18246.  va_start(argp,msgformat);
  18247.  vsprintf(buf,msgformat,argp);
  18248.  va_end(argp);
  18249.  
  18250.  cp = strchr(buf,';');
  18251.  if (cp) {
  18252.   *cp = '\0';
  18253.   strncpy(zerrsm,buf, sizeof(zerrsm));
  18254.   strncpy(zerrlm,cp+1,sizeof(zerrlm));
  18255.  }
  18256.  else {
  18257.   strcpy(zerrsm,"");
  18258.   strncpy(zerrlm,buf,sizeof(zerrlm));
  18259.  }
  18260.  
  18261.  zerrsm[sizeof(zerrsm)-1] = '\0';
  18262.  zerrlm[sizeof(zerrlm)-1] = '\0';
  18263.  
  18264.  if (msghelp) strcpy(zerrhm, msghelp);
  18265.  else         strcpy(zerrhm, "*"    );
  18266.  
  18267.  if (np->batch_mode) {
  18268.    if (!*zerrsm) {
  18269.      switch (msgtype) {
  18270.        case NOTIFY_MSG:    strcpy(zerrsm,"Note");  break;
  18271.        case WARNING_MSG:
  18272.        case CRITICAL_MSG:
  18273.        default:            strcpy(zerrsm,"Error"); break;
  18274.      }
  18275.    }
  18276.    fprintf(np->batch_outfile,"%s: %s\n", zerrsm, zerrlm);
  18277.    return;
  18278.  }
  18279.  
  18280.  switch (msgtype) {
  18281.    case NOTIFY_MSG:    strcpy(zerralrm,"NO "); break;
  18282.    case WARNING_MSG:
  18283.    case CRITICAL_MSG:
  18284.    default:            strcpy(zerralrm,"YES"); break;
  18285.  }
  18286.  
  18287.  (void)NNMivput(np,"ZERRSM ",  zerrsm,   -1);
  18288.  (void)NNMivput(np,"ZERRLM ",  zerrlm,   -1);
  18289.  (void)NNMivput(np,"ZERRHM ",  zerrhm,   -1);
  18290.  (void)NNMivput(np,"ZERRALRM ",zerralrm, -1);
  18291.  
  18292.  np->setmsg = TRUE;
  18293.  
  18294.  return; 
  18295. }
  18296.  
  18297. ./   ADD NAME=NNMPNG,SSI=010D0051
  18298.  
  18299.  /********************************************************************/
  18300.  /*                                                                  */
  18301.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  18302.  /*                                                                  */
  18303.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  18304.  /* including the implied warranties of merchantability and fitness, */
  18305.  /* are expressly denied.                                            */
  18306.  /*                                                                  */
  18307.  /* Provided this copyright notice is included, this software may    */
  18308.  /* be freely distributed and not offered for sale.                  */
  18309.  /*                                                                  */
  18310.  /* Changes or modifications may be made and used only by the maker  */
  18311.  /* of same, and not further distributed.  Such modifications should */
  18312.  /* be mailed to the author for consideration for addition to the    */
  18313.  /* software and incorporation in subsequent releases.               */
  18314.  /*                                                                  */
  18315.  /********************************************************************/
  18316.  
  18317. #pragma  csect(code,  "NN@PNG  ")
  18318. #pragma  csect(static,"NN$PNG  ")
  18319. #include "nn.h"
  18320.  
  18321. /****** Set articles missing based on XHDR info. *********************/
  18322.  
  18323. static void
  18324. set_articles_missing(np,gp,anum,xnum)
  18325. Rstruc nncb      *np;
  18326. Rstruc newsgroup *gp;
  18327. int               anum;
  18328. int               xnum;
  18329. {
  18330.  VARK            *vp;
  18331.  
  18332.  while (anum < xnum) {
  18333.    if (np->debug_file) {
  18334.      fprintf(np->debug_file, "Setting article %d missing\n",anum);
  18335.    }
  18336.    vp = &GETVARK(gp,anum);
  18337.    if (IsUnread(*vp)) gp->unread_count--;
  18338.    SetMissingRead(*vp);
  18339.    anum++;
  18340.  }
  18341.  
  18342.  return; 
  18343. }
  18344.  
  18345. /****** Do XHDR stuff for newsgroup. *********************************/
  18346.  
  18347. static void
  18348. do_xhdr(np,gp,allp)
  18349. Rstruc nncb         *np;
  18350. Rstruc newsgroup    *gp;
  18351. Bool                 allp;
  18352. {
  18353.  char               *lp;
  18354.  char               *xhdr_subject;
  18355.  VARK               *vplow;
  18356.  VARK               *vphigh;
  18357.  VARK               *vpfirst;
  18358.  VARK               *vplast;
  18359.  int                 range;
  18360.  int                 xhdr_article_number;
  18361.  int                 scan_count;
  18362.  int                 xhdr_low;
  18363.  int                 xhdr_high;
  18364.  int                 anum;
  18365.  
  18366.  /* If we need to know about missing articles,
  18367.   * we try to determine it via XHDR.
  18368.   *
  18369.   *    We don't do anything useful with the headers yet.  We should.
  18370.   *    That requires doing something with the allocation of the
  18371.   *    newsarticle structures.
  18372.   *
  18373.   * We use XHDR when:
  18374.   *
  18375.   * (1) the total article count is less than the difference between
  18376.   *     the low and high count from the GROUP command
  18377.   *
  18378.   * (2) there are null (never-retrieved) articles
  18379.   *
  18380.   * Fine, but requires looping around the article vector.
  18381.   * Now, if we only want unread articles, we don't want to XHDR
  18382.   * the whole thing, so in that case we only do this if there are
  18383.   * any null-and-unread articles.
  18384.   *
  18385.   * *** this is still no good because articles are set missing
  18386.   * *** but cannot be set present if we don't know if they will
  18387.   * *** be eligible or not.  I will HAVE to keep the subject and
  18388.   * *** set the article pointer to a placeholder with the subject,
  18389.   * *** which means more article structures allocated, but that is
  18390.   * *** probably the best thing to do.
  18391.   *
  18392.   * Solution: we call this routine only when a group migrates
  18393.   * from unselected to selected status - either when it goes
  18394.   * from never-selected to selected-unread, from never-selected
  18395.   * to selected-all, or from selected-unread to selected-all.
  18396.   * The first of the above cases is where allp is set to false
  18397.   * so that we don't XHDR the whole thing just for a few unread items.
  18398.   *
  18399.   */
  18400.  
  18401.  if (!gp->article_vector) return;
  18402.  if (np->xhdr_not_available) return;
  18403.  
  18404.  range = gp->vector_last - gp->vector_first + 1;
  18405.  if (range <= gp->article_count) return;
  18406.  
  18407.  vpfirst = &GETVARKFIRST(gp);
  18408.  vplast  = &GETVARKLAST(gp);
  18409.  
  18410.  if (allp) {
  18411.    for (vplow = vpfirst; vplow <= vplast; vplow++) {
  18412.      if (IsNull(*vplow)) break;
  18413.    }
  18414.    if (vplow > vplast) return; /* if no null articles */
  18415.    for (vphigh = vplast; vphigh > vplow; vphigh--) {
  18416.      if (IsNull(*vphigh)) break;
  18417.    }
  18418.  }
  18419.  else {
  18420.    for (vplow = vpfirst; vplow <= vplast; vplow++) {
  18421.      if (IsNull(*vplow) && IsUnread(*vplow)) break;
  18422.    }
  18423.    if (vplow > vplast) return; /* if no null articles */
  18424.    for (vphigh = vplast; vphigh > vplow; vphigh--) {
  18425.      if (IsNull(*vphigh) && IsUnread(*vphigh)) break;
  18426.    }
  18427.  }
  18428.  
  18429.  xhdr_low  = VARK2NUMBER(gp,vplow);
  18430.  xhdr_high = VARK2NUMBER(gp,vphigh);
  18431.  
  18432.  /* Send "XHDR SUBJECT nnn-nnn" to news server. */
  18433.  
  18434.  NNMestng(np,NULL);  /* set server "GROUP" if necessary */
  18435.                      /* e.g. going from unread-only to all */
  18436.  
  18437.  sprintf(np->nntp_command,"XHDR SUBJECT %d-%d",xhdr_low,xhdr_high);
  18438.  if (!NNMsockt(np)) return;          /* Send socket command to server */
  18439.  
  18440.  if (!NNMgsrvl(np,&lp)) return;        /* Get server line */
  18441.  switch (np->nntp_message_num) {
  18442.    case 221:                           /* subject fields follow */
  18443.              np->xhdr_not_available = FALSE;
  18444.              break;
  18445.    case 500:                           /* command unrecognized  */
  18446.              np->xhdr_not_available = TRUE;
  18447.              break;
  18448.    default:
  18449.              NNMrperr(np);        /* Report protocol error */
  18450.              return;
  18451.  }
  18452.  
  18453.  if (np->xhdr_not_available) return;
  18454.  
  18455.  /* assert np->sending_text == TRUE; */
  18456.  
  18457.  anum = xhdr_low;
  18458.  
  18459.  for (;;) {
  18460.  
  18461.    if (!NNMgsrvl(np,&lp))    return;   /* Get server line */
  18462.    if (lp == NULL)           break;
  18463.    if (strcmp(lp,".") == 0)  break;
  18464.  
  18465.    if (1 != sscanf(np->nntp_message_text, "%d %n",
  18466.                    &xhdr_article_number, &scan_count)) {
  18467.      NNMrbfm(np);   /* Report bad format message */
  18468.      return;
  18469.    }
  18470.  
  18471.    xhdr_subject = np->nntp_message_text + scan_count;
  18472.  
  18473.    if (np->debug_file) {
  18474.      fprintf(np->debug_file,"XHDR: article='%d', subject='%s'\n",
  18475.                             xhdr_article_number, xhdr_subject);
  18476.    }
  18477.    set_articles_missing(np,gp,anum,xhdr_article_number);
  18478.    anum = xhdr_article_number + 1;
  18479.  }
  18480.  
  18481.  set_articles_missing(np,gp,anum,xhdr_high);
  18482.  
  18483.  return; 
  18484. }
  18485.  
  18486. /****** Pick newsgroup. **********************************************/
  18487.  
  18488. Bool
  18489. NNMpng(np,gp,do_titles,do_sort)
  18490. Rstruc nncb          *np;
  18491. Rstruc newsgroup     *gp;
  18492. Fool                  do_titles;
  18493. Fool                  do_sort;
  18494. {
  18495.  Rstruc newsgroup    *gp1;
  18496.  Bool                 result = TRUE;
  18497.  Bool                 was_selected_unread;
  18498.  Bool                 was_selected_read;
  18499.  
  18500.  np->current_newsgroup   = gp;
  18501.  np->newsgroup_selected  = FALSE;
  18502.  np->newsgroup_not_found = FALSE;
  18503.  
  18504.  was_selected_read   = GroupSelectedRead(gp);
  18505.  was_selected_unread = GroupSelectedUnread(gp);
  18506.  
  18507.  if (!np->batch_mode) {
  18508.    (void)NNMivput(np,"NNGROUP ",gp->name,-1);
  18509.  }
  18510.  
  18511.  if (GroupSelected(gp)) {
  18512.    if (np->show_all_articles) {
  18513.      SetGroupSelectedRead(gp);
  18514.    }
  18515.    gp1 = gp;
  18516.  }
  18517.  else {
  18518.    gp1 = NNMdng(np,gp,NULL);  /* do newsgroup by address */
  18519.  }
  18520.  
  18521.  if (!gp1) {
  18522.    result = FALSE;
  18523.  }
  18524.  else if (np->newsgroup_not_found) {
  18525.    SetNoSuchGroup(gp);
  18526.    gp->article_count = 0;
  18527.    gp->unread_count  = 0;
  18528.    result = FALSE;
  18529.  }
  18530.  else {
  18531.    gp = gp1;;
  18532.  
  18533.    if (!was_selected_read && GroupSelectedRead(gp)) {
  18534.      do_xhdr(np,gp,TRUE);             /* do XHDR stuff for all */
  18535.    }
  18536.    else if (!was_selected_unread && GroupSelectedUnread(gp)) {
  18537.      do_xhdr(np,gp,FALSE);            /* do XHDR stuff for unread */
  18538.    }
  18539.  
  18540.    if (do_titles) (void)NNMrart(np,gp,FALSE,TRUE);
  18541.    if (do_sort)   (void)NNMsort(np,gp);
  18542.  
  18543.    result = NNMvar(np,gp);                   /* View articles */
  18544.  }
  18545.  
  18546.  np->current_newsgroup = NULL;
  18547.  np->newsgroup_selected = FALSE;
  18548.  
  18549.  /* hack to position newsgroup display*/
  18550.  
  18551.  strcpy(np->nngroup, gp->name);
  18552.  
  18553.  return result;
  18554. }
  18555.  
  18556. ./   ADD NAME=NNMQAR,SSI=01050011
  18557.  
  18558.  /********************************************************************/
  18559.  /*                                                                  */
  18560.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  18561.  /*                                                                  */
  18562.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  18563.  /* including the implied warranties of merchantability and fitness, */
  18564.  /* are expressly denied.                                            */
  18565.  /*                                                                  */
  18566.  /* Provided this copyright notice is included, this software may    */
  18567.  /* be freely distributed and not offered for sale.                  */
  18568.  /*                                                                  */
  18569.  /* Changes or modifications may be made and used only by the maker  */
  18570.  /* of same, and not further distributed.  Such modifications should */
  18571.  /* be mailed to the author for consideration for addition to the    */
  18572.  /* software and incorporation in subsequent releases.               */
  18573.  /*                                                                  */
  18574.  /********************************************************************/
  18575.  
  18576. #pragma  csect(code,  "NN@QAR  ")
  18577. #pragma  csect(static,"NN$QAR  ")
  18578. #include "nn.h"
  18579.  
  18580. #define OUT1(A)       (void)NNMouttx(np,(A),NULL)
  18581. #define OUT2(A,B)     sprintf(temp,(A),(B)),     OUT1(temp)
  18582. #define OUT3(A,B,C)   sprintf(temp,(A),(B),(C)), OUT1(temp)
  18583. #define ADD1(A)       strcat(stat,(A))
  18584. #define ADD2(A,B)     sprintf(temp,(A),(B)),     ADD1(temp)
  18585.  
  18586. /****** Query article. ***********************************************/
  18587.  
  18588. Bool
  18589. NNMqar(np,ap)
  18590. Rstruc nncb         *np;
  18591. Rstruc newsarticle  *ap;
  18592. {
  18593.  Rstruc newsgroup   *gp;
  18594.  char                stat[129];
  18595.  char                temp[129];
  18596.  
  18597.  gp = np->current_newsgroup;
  18598.  
  18599.  if (!gp) {
  18600.   CRIT1("No current newsgroup.  This should never happen.");
  18601.   return FALSE;
  18602.  }
  18603.  
  18604.  NNMclrtx(np,NULL);
  18605.  
  18606.  if (ap == V_NULL_ARTICLE) {
  18607.    OUT1("Null article");
  18608.  }
  18609.  
  18610.  else if (ap == V_MISSING_ARTICLE) {
  18611.    OUT1("Missing article");
  18612.  }
  18613.  
  18614.  else {
  18615.  
  18616.    OUT1("");
  18617.    OUT3("  Struct at %8.8X: Article %d", ap, ap->number);
  18618.    OUT1("");
  18619.    OUT2("status.........................%2.2X", ap->status);
  18620.    if (NoSuchArticle(ap))          OUT1(" NoSuchArticle"        );
  18621.    if (ArticleAbsent(ap))          OUT1(" ArticleAbsent"        );
  18622.    if (ArticleError(ap))           OUT1(" ArticleError"         );
  18623.    if (ArticleBadData(ap))         OUT1(" ArticleBadData"       );
  18624.    if (ArticleHeadRetrieved(ap))   OUT1(" ArticleHeadRetrieved" );
  18625.    if (ArticleBodyRetrieved(ap))   OUT1(" ArticleBodyRetrieved" );
  18626.    strcpy(stat,"action.........................");
  18627.    switch (ap->action) {
  18628.      case NO_ACTION:             ADD1("NO_ACTION");             break;
  18629.      case READ:                  ADD1("READ");                  break;
  18630.      case RETRIEVED:             ADD1("RETRIEVED");             break;
  18631.      case EXTRACTED:             ADD1("EXTRACTED");             break;
  18632.      case PRINTED:               ADD1("PRINTED");               break;
  18633.      case UNREAD:                ADD1("UNREAD");                break;
  18634.      case MISSING:               ADD1("MISSING");               break;
  18635.      case ERROR:                 ADD1("ERROR");                 break;
  18636.      case CANCELLED:             ADD1("CANCELLED");             break;
  18637.      default:                    ADD2("%d",ap->action);         break;
  18638.    }
  18639.    OUT1(stat);
  18640.    OUT2("number.........................%d",    ap->number);
  18641.    OUT2("from...........................%s",    ap->from);
  18642.    OUT2("subject........................%s",    ap->subject);
  18643.    OUT2("date...........................%s",    ap->date);
  18644.    OUT2("message_id.....................%s",    ap->message_id);
  18645.  
  18646.    if (ap->csubject)
  18647.      OUT2("csubject.......................%s",  ap->csubject);
  18648.    else
  18649.      OUT1("csubject is NULL");
  18650.  
  18651.    OUT2("text line count................%d", ap->thdr.text_line_count);
  18652.    OUT2("text max length................%d", ap->thdr.text_max_length);
  18653.    OUT2("text max tab expanded length...%d",
  18654.                                 ap->thdr.text_max_tab_expanded_length);
  18655.    OUT2("text body line..............%8.8X",ap->thdr.text_body_line);
  18656.    OUT2("first text line.............%8.8X",ap->thdr.first_text_line);
  18657.    OUT2("current text line...........%8.8X",ap->thdr.current_text_line);
  18658.    OUT2("last text line..............%8.8X",ap->thdr.last_text_line);
  18659.  
  18660.  }
  18661.  
  18662.  NNMvtx(np,NULL,NULL);
  18663.  
  18664.  return TRUE;
  18665. }
  18666.  
  18667. ./   ADD NAME=NNMQNG,SSI=01100058
  18668.  
  18669.  /********************************************************************/
  18670.  /*                                                                  */
  18671.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  18672.  /*                                                                  */
  18673.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  18674.  /* including the implied warranties of merchantability and fitness, */
  18675.  /* are expressly denied.                                            */
  18676.  /*                                                                  */
  18677.  /* Provided this copyright notice is included, this software may    */
  18678.  /* be freely distributed and not offered for sale.                  */
  18679.  /*                                                                  */
  18680.  /* Changes or modifications may be made and used only by the maker  */
  18681.  /* of same, and not further distributed.  Such modifications should */
  18682.  /* be mailed to the author for consideration for addition to the    */
  18683.  /* software and incorporation in subsequent releases.               */
  18684.  /*                                                                  */
  18685.  /********************************************************************/
  18686.  
  18687. #pragma  csect(code,  "NN@QNG  ")
  18688. #pragma  csect(static,"NN$QNG  ")
  18689. #include "nn.h"
  18690.  
  18691. #define OUT1(A)       (void)NNMouttx(np,(A),NULL)
  18692. #define OUT2(A,B)     sprintf(temp,(A),(B)),     OUT1(temp)
  18693. #define OUT3(A,B,C)   sprintf(temp,(A),(B),(C)), OUT1(temp)
  18694. #define ADD1(A)       strcat(stat,(A))
  18695. #define ADD2(A,B)     sprintf(temp,(A),(B)),     ADD1(temp)
  18696.  
  18697. /****** Query newsgroup. *********************************************/
  18698.  
  18699. void
  18700. NNMqng(np,gp)
  18701. Rstruc nncb         *np;
  18702. Rstruc newsgroup    *gp;
  18703. {
  18704.  struct newsarticle *ap;
  18705.  int                 i;
  18706.  VARK               *vp;
  18707.  VARK               *vpfirst;
  18708.  VARK               *vplast;
  18709.  VARK              **wp;
  18710.  VARK              **wpfirst;
  18711.  VARK              **wplast;
  18712.  char                stat[129];
  18713.  char                temp[129];
  18714.  
  18715.  if (!gp) return;
  18716.  
  18717.  NNMclrtx(np,NULL);
  18718.  
  18719.  OUT1("");
  18720.  OUT3("    Struct at %8.8X: Newsgroup '%s'", gp, gp->name);
  18721.  OUT1("");
  18722.  OUT2("next.......................%8.8X", gp->next);
  18723.  OUT2("next2......................%8.8X", gp->next2);
  18724.  OUT2("next3......................%8.8X", gp->next3);
  18725.  OUT2("saved_newsrc_line..........%8.8X", gp->saved_newsrc_line);
  18726.  OUT2("article_vector.............%8.8X", gp->article_vector);
  18727.  OUT2("sort_vector................%8.8X", gp->sort_vector);
  18728.  OUT2("low_number.................%d",    gp->low_number);
  18729.  OUT2("high_number................%d",    gp->high_number);
  18730.  OUT2("vector_first...............%d",    gp->vector_first);
  18731.  OUT2("vector_last................%d",    gp->vector_last);
  18732.  OUT2("article_count..............%d",    gp->article_count);
  18733.  OUT2("unread_count...............%d",    gp->unread_count);
  18734.  OUT2("sort_count.................%d",    gp->sort_count);
  18735.  OUT2("article_vector_len.........%d",    gp->article_vector_len);
  18736.  OUT2("registered.................%d",    gp->registered);
  18737.  OUT2("saved_newsrc_data..........%s",    gp->saved_newsrc_data);
  18738.  OUT2("status.....................%2.2X", gp->status);
  18739.  if (NoSuchGroup(gp))         OUT1(" NoSuchGroup"           );
  18740.  if (NewGroup(gp))            OUT1(" NewGroup"              );
  18741.  if (GroupFromNewsrc(gp))     OUT1(" GroupFromNewsrc"       );
  18742.  if (GroupListed(gp))         OUT1(" GroupListed"           );
  18743.  if (GroupSelectedUnread(gp)) OUT1(" GroupSelectedUnread"   );
  18744.  if (GroupSelectedRead(gp))   OUT1(" GroupSelectedRead"     );
  18745.  if (GroupError(gp))          OUT1(" GroupError"            );
  18746.  if (GroupInTable(gp))        OUT1(" GroupInTable"          );
  18747.  OUT2("name.......................%s",    gp->name);
  18748.  if (gp->saved_newsrc_line) {
  18749.    OUT1("");
  18750.    OUT1("Saved newsrc line follows:");
  18751.    OUT1("");
  18752.    OUT1(gp->saved_newsrc_line);
  18753.    OUT1("");
  18754.    OUT1("");
  18755.  }
  18756.  
  18757.  if (gp->article_vector) {
  18758.    OUT1("");
  18759.    OUT1("Article vector follows:");
  18760.    OUT1("");
  18761.    vpfirst = &GETVARKFIRST(gp);
  18762.    vplast  = &GETVARKLAST(gp);
  18763.    for (vp = vpfirst, i = gp->vector_first; vp <= vplast; vp++,i++) {
  18764.      sprintf(stat," %10d: %8.8X    ",i,*vp);
  18765.      ap = VARK2PARTICLE(*vp);
  18766.      if (ap == V_NULL_ARTICLE)         ADD1("Null     ");
  18767.      else if (ap == V_MISSING_ARTICLE) ADD1("Missing  ");
  18768.      else                              ADD2("%8.8X ",ap);
  18769.      if (IsKnown(*vp))                 ADD1("Known   ");
  18770.      else                              ADD1("Unknown ");
  18771.      if (IsEligible(*vp))              ADD1("Eligible   ");
  18772.      else                              ADD1("Ineligible ");
  18773.      if (IsRead(*vp))                  ADD1("Read   ");
  18774.      else                              ADD1("Unread ");
  18775.      OUT1(stat);
  18776.    }
  18777.  }
  18778.  if (gp->sort_vector) {
  18779.    OUT1("");
  18780.    OUT1("Sort vector follows:");
  18781.    OUT1("");
  18782.    wpfirst = gp->sort_vector;
  18783.    wplast  = gp->sort_vector + gp->sort_count;
  18784.    for (wp = wpfirst; wp < wplast; wp++) {
  18785.      OUT3("     %8.8X: %8.8X",*wp,**wp);
  18786.    }
  18787.  }
  18788.  
  18789.  NNMvtx(np,NULL,NULL);
  18790.  
  18791.  return; 
  18792. }
  18793.  
  18794. ./   ADD NAME=NNMRARH,SSI=010B0033
  18795.  
  18796.  /********************************************************************/
  18797.  /*                                                                  */
  18798.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  18799.  /*                                                                  */
  18800.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  18801.  /*                                                                  */
  18802.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  18803.  /* including the implied warranties of merchantability and fitness, */
  18804.  /* are expressly denied.                                            */
  18805.  /*                                                                  */
  18806.  /* Provided this copyright notice is included, this software may    */
  18807.  /* be freely distributed and not offered for sale.                  */
  18808.  /*                                                                  */
  18809.  /* Changes or modifications may be made and used only by the maker  */
  18810.  /* of same, and not further distributed.  Such modifications should */
  18811.  /* be mailed to the author for consideration for addition to the    */
  18812.  /* software and incorporation in subsequent releases.               */
  18813.  /*                                                                  */
  18814.  /********************************************************************/
  18815.  
  18816. #pragma  csect(code,  "NN@RARH ")
  18817. #pragma  csect(static,"NN$RARH ")
  18818. #include "nn.h"
  18819.  
  18820. /****** Get article. *************************************************/
  18821.  
  18822. static struct newsarticle *
  18823. get_article(np,gp,vp,anum,cdp)
  18824. Rstruc nncb          *np;
  18825. Rstruc newsgroup     *gp;
  18826. VARK                 *vp;
  18827. int                   anum;
  18828. struct countdown     *cdp;
  18829. {
  18830.  struct newsarticle  *ap;
  18831.  char                *lp;
  18832.  char                *cp;
  18833.  struct textline     *tp;
  18834.  int                  header_index;
  18835.  char                 header_name[INTERNET_SIZE];
  18836.  
  18837.  if (anum <= 0) anum = VARK2NUMBER(gp,vp);
  18838.  
  18839.  SetUnknown(*vp);
  18840.  
  18841.  /* Allocate a struct newsarticle for this article */
  18842.  
  18843.  GETMAIN(ap, struct newsarticle, 1, "news article");
  18844.  if (!ap) {
  18845.    ERR2("There is not enough memory to retrieve article %d.", anum);
  18846.    SetIneligible(*vp);
  18847.    return NULL;
  18848.  }
  18849.  
  18850.  *vp = ((VARK)ap | VARK2BITS(*vp));
  18851.  
  18852.  memset(ap,0,sizeof(struct newsarticle));
  18853.  ClearArticleStatus(ap);
  18854.  ap->action = ERROR;
  18855.  ap->number = anum;
  18856.  
  18857.  if (!NNMestng(np,NULL)) {                 /* Establish newsgroup */
  18858.    SetArticleError(ap);
  18859.    SetIneligible(*vp);
  18860.    return NULL;
  18861.  }
  18862.  
  18863.  tp = NULL;
  18864.  
  18865.  /* If user asked for screen updates, do them here. */
  18866.  
  18867.  NNMupdt(np,cdp,"NNMLART2");
  18868.  
  18869.  /* Ask for the head of the article by number. */
  18870.  /* (Is it better to ask by message-id? Dunno) */
  18871.  
  18872.  sprintf(np->nntp_command,"HEAD %d",ap->number);
  18873.  if (!NNMsockt(np)) return FALSE;  /* Send socket command to server */
  18874.  
  18875.  if (NNMgsrvl(np,&lp)) {           /* Get server line */
  18876.    switch (np->nntp_message_num) {
  18877.      case 221:          /* article retrieved, head follows         */
  18878.                SetArticleHeadRetrieved(ap);
  18879.                break;
  18880.      case 423:          /*    no such article number in this group */
  18881.                SetNoSuchArticle(ap);
  18882.                ap->action = MISSING;
  18883.                break;
  18884.      case 430:          /*    no such article found                */
  18885.                SetArticleAbsent(ap);
  18886.                ap->action = MISSING;
  18887.                break;
  18888.      default:
  18889.                SetArticleError(ap);
  18890.                NNMrperr(np);        /* Report protocol error */
  18891.                break;
  18892.    }
  18893.  }
  18894.  
  18895.  if (!ArticleHeadRetrieved(ap)) {
  18896.    if IsUnread(*vp) gp->unread_count--;
  18897.    SetMissingRead(*vp);
  18898.    return NULL;
  18899.  }
  18900.  
  18901.  /* Scan the text for headers and extract the subject and whatever. */
  18902.  
  18903.  ap->subject    = "";
  18904.  ap->from       = "";
  18905.  ap->message_id = "";
  18906.  ap->date       = "";
  18907.  
  18908.  np->sending_text = TRUE; /* Stuff following is header text */
  18909.  
  18910.  for (;;) {
  18911.  
  18912.    if (!NNMgsrvl(np,&lp))            break;  /* Get server line */
  18913.    if (lp == NULL)                   break;
  18914.    if (np->server_finished_replying) break;
  18915.    if (!(tp=NNMouttx(np,lp,ap)))     break;  /* Output text line */
  18916.  
  18917.    if (*(cp=tp->tab_expanded_text) == ' ') continue;
  18918.  
  18919.    header_name[0] = '\0';
  18920.    header_index = 0;
  18921.    while (*cp != ':') {
  18922.      if (*cp == '\0' || *cp == ' ') {
  18923.        NNMdump(np,"Warning, bad header line",lp,strlen(lp));
  18924.        SetArticleBadData(ap);
  18925.        break;
  18926.      }
  18927.      else header_name[header_index++] = toupper(*cp++);
  18928.    }
  18929.  
  18930.    header_name[header_index] = '\0';
  18931.    cp = skip_whitespace(cp+1);
  18932.    if      (EQUAL(header_name,"FROM")) {
  18933.            ap->from = cp;
  18934.    }
  18935.    else if (EQUAL(header_name,"SUBJECT")) {
  18936.            ap->subject = cp;
  18937.    }
  18938.    else if (EQUAL(header_name,"MESSAGE-ID")) {
  18939.            ap->message_id = cp;
  18940.    }
  18941.    else if (EQUAL(header_name,"DATE")) {
  18942.            cp = strpbrk(cp,"0123456789");
  18943.            if (!cp) cp = "*BAD DATE*";
  18944.            ap->date = cp;
  18945.    }
  18946.  }
  18947.  
  18948.  /* Prepare ISPF variables for possible panel or message processing. */
  18949.  
  18950.  if (!np->batch_mode) {
  18951.    (void)NNMivput(np,"NNTSUBJ " ,ap->subject,-1);
  18952.  }
  18953.  
  18954.  /* Since we retrieved the article, it can't be missing, can it? */
  18955.  
  18956.  SetKnown(*vp);
  18957.  ap->action = NO_ACTION;
  18958.  
  18959.  return ap;
  18960.  
  18961. }
  18962.  
  18963. /****** Retrieve article header. *************************************/
  18964.  
  18965. struct newsarticle *
  18966. NNMrarh(np,gp,vp,anum,cdp)
  18967. Rstruc nncb          *np;
  18968. Rstruc newsgroup     *gp;
  18969. VARK                 *vp;
  18970. int                   anum;
  18971. struct countdown     *cdp;
  18972. {
  18973.  Rstruc newsarticle  *ap;
  18974.  
  18975.  /* Note that either vp or anum may be null (zero), but NOT BOTH. */
  18976.  
  18977.  if (!vp) vp = &GETVARK(gp,anum);
  18978.  ap = VARK2PARTICLE(*vp);
  18979.  
  18980.  if (ap == V_NULL_ARTICLE)  return get_article(np,gp,vp,anum,cdp);
  18981.  else if (ap == V_MISSING_ARTICLE) return NULL;
  18982.  else                              return ap;
  18983.  
  18984. }
  18985.  
  18986. ./   ADD NAME=NNMRART,SSI=010C0036
  18987.  
  18988.  /********************************************************************/
  18989.  /*                                                                  */
  18990.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  18991.  /*                                                                  */
  18992.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  18993.  /*                                                                  */
  18994.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  18995.  /* including the implied warranties of merchantability and fitness, */
  18996.  /* are expressly denied.                                            */
  18997.  /*                                                                  */
  18998.  /* Provided this copyright notice is included, this software may    */
  18999.  /* be freely distributed and not offered for sale.                  */
  19000.  /*                                                                  */
  19001.  /* Changes or modifications may be made and used only by the maker  */
  19002.  /* of same, and not further distributed.  Such modifications should */
  19003.  /* be mailed to the author for consideration for addition to the    */
  19004.  /* software and incorporation in subsequent releases.               */
  19005.  /*                                                                  */
  19006.  /********************************************************************/
  19007.  
  19008. #pragma  csect(code,  "NN@RART ")
  19009. #pragma  csect(static,"NN$RART ")
  19010. #include "nn.h"
  19011.  
  19012. /****** Retrieve all article titles. *********************************/
  19013.  
  19014. int
  19015. NNMrart(np,gp,not_just_unread,not_just_only)
  19016. Rstruc nncb         *np;
  19017. Rstruc newsgroup    *gp;
  19018. Fool                 not_just_unread;
  19019. Fool                 not_just_only;
  19020. {
  19021.  struct newsarticle *ap;
  19022.  VARK               *vp;
  19023.  VARK               *vpfirst;
  19024.  VARK               *vplast;
  19025.  VARK              **wp;
  19026.  VARK              **wpfirst;
  19027.  VARK              **wplast;
  19028.  int                 count;
  19029.  struct countdown    cd;
  19030.  Bool                save_show_all_articles;
  19031.  char                save_article_only_char;
  19032.  
  19033.  np->bypass_header_retrieval = FALSE;
  19034.  
  19035.  if (!gp->article_vector) return 0;
  19036.  
  19037.  vpfirst = &GETVARKFIRST(gp);
  19038.  vplast  = &GETVARKLAST(gp);
  19039.  
  19040.  if (np->updatefreq < 0) {
  19041.    cd.do_update = FALSE;
  19042.    cd.done      = 0;
  19043.    cd.to_do     = 0;
  19044.  }
  19045.  else {
  19046.    cd.do_update = TRUE;
  19047.    cd.done      = 0;
  19048.    cd.to_do     = 0;
  19049.    if (not_just_unread) {
  19050.      for (vp = vpfirst; vp <= vplast; vp++) {
  19051.        if (IsNull(*vp)) cd.to_do++;
  19052.      }
  19053.    }
  19054.    else {
  19055.      for (vp = vpfirst; vp <= vplast; vp++) {
  19056.        if (IsNull(*vp) && IsUnread(*vp)) cd.to_do++;
  19057.      }
  19058.    }
  19059.  }
  19060.  
  19061.  if (not_just_unread) {
  19062.    save_show_all_articles = np->show_all_articles;
  19063.    np->show_all_articles = TRUE;
  19064.  }
  19065.  if (not_just_only) {
  19066.    save_article_only_char = np->article_only_string[0];
  19067.    np->article_only_string[0] = '\0';
  19068.  }
  19069.  
  19070.  count = 0;
  19071.  
  19072.  if (gp->sort_vector) {
  19073.    wpfirst = gp->sort_vector;
  19074.    wplast  = gp->sort_vector + gp->sort_count - 1;
  19075.    for (wp = wpfirst; wp <= wplast; wp++) {
  19076.      SetUnknown(**wp);
  19077.      if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) { /* Choose article */
  19078.        count++;
  19079.      }
  19080.    }
  19081.  }
  19082.  else {
  19083.    for (vp = vpfirst; vp <= vplast; vp++) {
  19084.      SetUnknown(*vp);
  19085.      if (NNMcar(np,gp,0,vp,NULL,&cd,RETRIEVE)) { /* Choose article */
  19086.        count++;
  19087.      }
  19088.    }
  19089.  }
  19090.  
  19091.  /*
  19092.   * IMPORTANT: On return, articles are set eligible if their titles
  19093.   * have been retrieved, even if we fudged the criteria.  We could
  19094.   * reset them all to unknown, but NNMsort needs this information,
  19095.   * so it is the responsibility of the caller of NNMrart to reset
  19096.   * all the statuses if it called NNMrart with fudging turned on.
  19097.   */
  19098.  
  19099.  if (not_just_unread) {
  19100.    np->show_all_articles = save_show_all_articles;
  19101.  }
  19102.  if (not_just_only) {
  19103.    np->article_only_string[0] = save_article_only_char;
  19104.  }
  19105.  
  19106.  return count; /* number of eligible and retrieved, for NNMsort */
  19107. }
  19108.  
  19109. ./   ADD NAME=NNMRBFM,SSI=01000057
  19110.  
  19111.  /********************************************************************/
  19112.  /*                                                                  */
  19113.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19114.  /*                                                                  */
  19115.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19116.  /* including the implied warranties of merchantability and fitness, */
  19117.  /* are expressly denied.                                            */
  19118.  /*                                                                  */
  19119.  /* Provided this copyright notice is included, this software may    */
  19120.  /* be freely distributed and not offered for sale.                  */
  19121.  /*                                                                  */
  19122.  /* Changes or modifications may be made and used only by the maker  */
  19123.  /* of same, and not further distributed.  Such modifications should */
  19124.  /* be mailed to the author for consideration for addition to the    */
  19125.  /* software and incorporation in subsequent releases.               */
  19126.  /*                                                                  */
  19127.  /********************************************************************/
  19128.  
  19129. #pragma  csect(code,  "NN@RBFM ")
  19130. #pragma  csect(static,"NN$RBFM ")
  19131. #include "nn.h"
  19132.  
  19133. /****** Report bad format message. ***********************************/
  19134.  
  19135. void
  19136. NNMrbfm(np)
  19137. Rstruc nncb  *np;
  19138. {
  19139.  
  19140.  NNMclrtx(np,NULL);                         /* Clear text */
  19141.  
  19142.  CRIT2("NNTP message from server %s has invalid format.", np->nnserver);
  19143.  
  19144.  (void)NNMouttx(np,np->server_buf,NULL);    /* Output text line */
  19145.  NNMvtx(np,NULL,NULL);                      /* View text */
  19146.  
  19147.  return; 
  19148. }
  19149.  
  19150. ./   ADD NAME=NNMRECON,SSI=01030026
  19151.  
  19152.  /********************************************************************/
  19153.  /*                                                                  */
  19154.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19155.  /*                                                                  */
  19156.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19157.  /* including the implied warranties of merchantability and fitness, */
  19158.  /* are expressly denied.                                            */
  19159.  /*                                                                  */
  19160.  /* Provided this copyright notice is included, this software may    */
  19161.  /* be freely distributed and not offered for sale.                  */
  19162.  /*                                                                  */
  19163.  /* Changes or modifications may be made and used only by the maker  */
  19164.  /* of same, and not further distributed.  Such modifications should */
  19165.  /* be mailed to the author for consideration for addition to the    */
  19166.  /* software and incorporation in subsequent releases.               */
  19167.  /*                                                                  */
  19168.  /********************************************************************/
  19169.  
  19170. #pragma  csect(code,  "NN@RECON")
  19171. #pragma  csect(static,"NN$RECON")
  19172. #include "nn.h"
  19173.  
  19174. /****** Reconnect to server. *****************************************/
  19175.  
  19176. Bool
  19177. NNMrecon(np)
  19178. Rstruc nncb        *np;
  19179. {
  19180.  struct newsgroup  *gp;
  19181.  char               save_command[CLIENT_BUF_MSGSIZE+4];
  19182.  
  19183.  if (np->dont_reconnect) {
  19184.    CRIT2(
  19185.  "Disconnected from server %s.  Reconnection will not be attempted.",
  19186.          np->nnserver);
  19187.    return FALSE;
  19188.  }
  19189.  
  19190.  np->connected_to_server   = FALSE;
  19191.  np->reconnect_in_progress = TRUE;
  19192.  
  19193.  if (!np->batch_mode) {
  19194.    (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  19195.    (void)NNMispf(np,"DISPLAY PANEL(NNMLRCON)");
  19196.  }
  19197.  
  19198.  /*
  19199.   * fprintf(stderr,"Lost connection, possible timeout.\n");
  19200.   * fprintf(stderr,"Attempting reconnection to news server %s (%s)\n",
  19201.   *                np->server_hostname,
  19202.   *                np->server_ip_addrstr);
  19203.   */
  19204.  
  19205.  if (!NNMconn(np)) {                 /* Connect to news server */
  19206.    CRIT2("Reconnection failed to server %s after disconnect.",
  19207.          np->nnserver);
  19208.    return FALSE;
  19209.  }
  19210.  
  19211.  /* If there is a current newsgroup and we're not currently trying
  19212.   * to issue a "GROUP" command, then reestablish server's state.
  19213.   */
  19214.  
  19215.  if ((gp=np->current_newsgroup)
  19216.      && memcmp(np->nntp_command,"GROUP ",6)) /* not "GROUP" */ {
  19217.  
  19218.    if (!np->batch_mode) {
  19219.      (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  19220.      (void)NNMispf(np,"DISPLAY PANEL(NNMLRSNG)");
  19221.    }
  19222.  
  19223.    strcpy(save_command,np->nntp_command);
  19224.    /* Establish newsgroup */
  19225.    if (!NNMestng(np,gp->name)) {
  19226.      strcpy(np->nntp_command,save_command);
  19227.      CRIT3(
  19228.        "Reselect of newsgroup %s failed during reconnection to %s.",
  19229.        gp->name, np->nnserver);
  19230.      return FALSE;
  19231.    }
  19232.    strcpy(np->nntp_command,save_command);
  19233.  }
  19234.  np->reconnect_in_progress = FALSE;
  19235.  return TRUE;
  19236. }
  19237.  
  19238. ./   ADD NAME=NNMRPERR,SSI=01000026
  19239.  
  19240.  /********************************************************************/
  19241.  /*                                                                  */
  19242.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19243.  /*                                                                  */
  19244.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19245.  /* including the implied warranties of merchantability and fitness, */
  19246.  /* are expressly denied.                                            */
  19247.  /*                                                                  */
  19248.  /* Provided this copyright notice is included, this software may    */
  19249.  /* be freely distributed and not offered for sale.                  */
  19250.  /*                                                                  */
  19251.  /* Changes or modifications may be made and used only by the maker  */
  19252.  /* of same, and not further distributed.  Such modifications should */
  19253.  /* be mailed to the author for consideration for addition to the    */
  19254.  /* software and incorporation in subsequent releases.               */
  19255.  /*                                                                  */
  19256.  /********************************************************************/
  19257.  
  19258. #pragma  csect(code,  "NN@RPERR")
  19259. #pragma  csect(static,"NN$RPERR")
  19260. #include "nn.h"
  19261.  
  19262. /****** Report protocol error. ***************************************/
  19263.  
  19264. void
  19265. NNMrperr(np)
  19266. Rstruc nncb  *np;
  19267. {
  19268.  
  19269.  NNMclrtx(np,NULL);                         /* Clear text */
  19270.  
  19271.  CRIT2("NNTP protocol error.  Unexpected response by server %s.",
  19272.        np->nnserver);
  19273.  
  19274.  (void)NNMouttx(np,np->server_buf,NULL);    /* Output text line */
  19275.  NNMvtx(np,NULL,NULL);                      /* View text */
  19276.  
  19277.  return; 
  19278. }
  19279.  
  19280. ./   ADD NAME=NNMSAVE,SSI=01000057
  19281.  
  19282.  /********************************************************************/
  19283.  /*                                                                  */
  19284.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19285.  /*                                                                  */
  19286.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19287.  /* including the implied warranties of merchantability and fitness, */
  19288.  /* are expressly denied.                                            */
  19289.  /*                                                                  */
  19290.  /* Provided this copyright notice is included, this software may    */
  19291.  /* be freely distributed and not offered for sale.                  */
  19292.  /*                                                                  */
  19293.  /* Changes or modifications may be made and used only by the maker  */
  19294.  /* of same, and not further distributed.  Such modifications should */
  19295.  /* be mailed to the author for consideration for addition to the    */
  19296.  /* software and incorporation in subsequent releases.               */
  19297.  /*                                                                  */
  19298.  /********************************************************************/
  19299.  
  19300. #pragma  csect(code,  "NN@SAVE ")
  19301. #pragma  csect(static,"NN$SAVE ")
  19302. #include "nn.h"
  19303. #include "nnbatch.h"
  19304.  
  19305. /****** Save NEWSRC file. ********************************************/
  19306.  
  19307. Bool
  19308. NNMsave(np,rest)
  19309. Rstruc nncb         *np;
  19310. char                *rest;
  19311. {
  19312.  Rstruc batch       *bp;
  19313.  
  19314.  if (np->batch_mode) {
  19315.    bp = np->batch_hook;
  19316.    if (GETB("CHECKPOINT") == FALSE) return TRUE;
  19317.  }
  19318.  
  19319.  NNMcnrf(np,NULL,TRUE);  /* Close NEWSRC file */
  19320.  
  19321.  /* Reopen the file for input.  Don't let anybody else sneak in. */
  19322.  
  19323.  if (!(np->newsrc_file = fopen(np->newsrc_to_open,"r"))) {
  19324.    perror("Cannot reopen NEWSRC file");
  19325.  }
  19326.  
  19327.  return TRUE;
  19328. }
  19329.  
  19330. ./   ADD NAME=NNMSOCKT,SSI=01030031
  19331.  
  19332.  /********************************************************************/
  19333.  /*                                                                  */
  19334.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19335.  /*                                                                  */
  19336.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19337.  /* including the implied warranties of merchantability and fitness, */
  19338.  /* are expressly denied.                                            */
  19339.  /*                                                                  */
  19340.  /* Provided this copyright notice is included, this software may    */
  19341.  /* be freely distributed and not offered for sale.                  */
  19342.  /*                                                                  */
  19343.  /* Changes or modifications may be made and used only by the maker  */
  19344.  /* of same, and not further distributed.  Such modifications should */
  19345.  /* be mailed to the author for consideration for addition to the    */
  19346.  /* software and incorporation in subsequent releases.               */
  19347.  /*                                                                  */
  19348.  /********************************************************************/
  19349.  
  19350. #pragma  csect(code,  "NN@SOCKT")
  19351. #pragma  csect(static,"NN$SOCKT")
  19352. #include "nn.h"
  19353.  
  19354. /****** Output one data line for the server. *************************/
  19355.  
  19356. Bool
  19357. NNMsockt(np)
  19358. Rstruc nncb    *np;
  19359. {
  19360.  int            nntp_bytes;
  19361.  int            writrc;
  19362.  char          *s_buf;
  19363.  
  19364.  nntp_bytes = strlen(np->nntp_command);
  19365.  
  19366.  /* Before sending a request to the server, do a cleanup operation
  19367.     to make sure that no more responses are coming from the server. */
  19368.  
  19369.  NNMesrvr(np);           /* End server read */
  19370.  
  19371.  memcpy(np->client_buf,np->nntp_command,nntp_bytes);
  19372.  np->client_buf[nntp_bytes  ] = CARRIAGE_RETURN;
  19373.  np->client_buf[nntp_bytes+1] = LINE_FEED;
  19374.  
  19375.  if (np->receiving_text &&
  19376.      nntp_bytes == 1    &&
  19377.      np->client_buf[0] == '.') {
  19378.    np->receiving_text = FALSE;
  19379.  }
  19380.  
  19381.  if (np->debug_mode)
  19382.     NNMdump(np,"Writing to server",np->client_buf,nntp_bytes+2);
  19383.  
  19384. #ifdef MVS
  19385.  EBCDIC_TO_ASCII(np->client_buf,nntp_bytes+2);
  19386. #endif
  19387.  
  19388.  writrc = write(np->socknum, np->client_buf, nntp_bytes+2);
  19389.  if (writrc < 0) {
  19390.    np->connection_broken = TRUE;
  19391.    if (!np->reconnect_in_progress) {
  19392.      GETMAIN(s_buf,char,CLIENT_BUF_MSGSIZE+4,"socket buffer");
  19393.      if (s_buf) {
  19394.        memcpy(s_buf,np->client_buf,nntp_bytes+2);
  19395.        if (NNMrecon(np)) {     /* Reconnect to server */
  19396.          writrc = write(np->socknum, s_buf, nntp_bytes+2);
  19397.        } 
  19398.        FREEMAIN(s_buf, "old socket buffer");
  19399.      }
  19400.    }
  19401.  }
  19402.  if (writrc < 0) {
  19403.    CRIT2("TCP/IP error: write() failed to send data to server %s.",
  19404.          np->nnserver);
  19405.    return FALSE;
  19406.  }
  19407.  
  19408.  NNMssrvr(np);      /* Start server read */
  19409.  
  19410.  return TRUE;
  19411. }
  19412.  
  19413. ./   ADD NAME=NNMSOPT,SSI=01010012
  19414.  
  19415.  /********************************************************************/
  19416.  /*                                                                  */
  19417.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19418.  /*                                                                  */
  19419.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  19420.  /*                                                                  */
  19421.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19422.  /* including the implied warranties of merchantability and fitness, */
  19423.  /* are expressly denied.                                            */
  19424.  /*                                                                  */
  19425.  /* Provided this copyright notice is included, this software may    */
  19426.  /* be freely distributed and not offered for sale.                  */
  19427.  /*                                                                  */
  19428.  /* Changes or modifications may be made and used only by the maker  */
  19429.  /* of same, and not further distributed.  Such modifications should */
  19430.  /* be mailed to the author for consideration for addition to the    */
  19431.  /* software and incorporation in subsequent releases.               */
  19432.  /*                                                                  */
  19433.  /********************************************************************/
  19434.  
  19435. #pragma  csect(code,  "NN@SOPT ")
  19436. #pragma  csect(static,"NN$SOPT ")
  19437. #include "nn.h"
  19438.  
  19439. #define BOOLOPTSET(A,B,C) \
  19440.    switch (A[0]) { \
  19441.      case  'n': \
  19442.      case  'N':   B = FALSE; break; \
  19443.      case  'y': \
  19444.      case  'Y':   B = TRUE; break; \
  19445.      case '\0': \
  19446.      default:     B = C; break; \
  19447.    }
  19448.  
  19449. /****** Set options that are stored in ISPF profile. *****************/
  19450.  
  19451. void
  19452. NNMsopt(np,which)
  19453. Rstruc nncb        *np;
  19454. enum user_option    which;
  19455. {
  19456.  int                arrows;
  19457.  char               tempinc [256];
  19458.  char               tempexc [256];
  19459.  char               nnmupdtf[ 12];
  19460.  char               nnextpow[  4];
  19461.  char               nnextpap[  4];
  19462.  char               nnupan  [  4];
  19463.  char               nnuprn  [  4];
  19464.  char               nnupra  [  4];
  19465.  char               nnngscr [  4];
  19466.  char               nnngcsr [  4];
  19467.  char               nnarscr [  4];
  19468.  char               nnarcsr [  4];
  19469.  char               nnarrows[  2];
  19470.  
  19471.  if (which == OPTION_ALL) {
  19472.    NNMispf(np, "VGET \
  19473. (NNRFCOPT NNRFCINC NNRFCEXC\
  19474.  NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP\
  19475.  NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS)\
  19476.  PROFILE");
  19477.  }
  19478.  
  19479.  if (which == OPTION_ALL || which == OPTION_HEADER) {
  19480.  
  19481.    (void)NNMivget(np,"NNRFCOPT ", np->nnrfcopt, sizeof(np->nnrfcopt));
  19482.    (void)NNMivget(np,"NNRFCINC ", tempinc, sizeof(tempinc));
  19483.    (void)NNMivget(np,"NNRFCEXC ", tempexc, sizeof(tempexc));
  19484.  
  19485.    if (!*np->nnrfcopt) strcpy(np->nnrfcopt,"A");
  19486.    sprintf(np->nnrfcinc," %s ",tempinc);
  19487.    sprintf(np->nnrfcexc," %s ",tempexc);
  19488.  
  19489.  }
  19490.  
  19491.  if (which == OPTION_ALL || which == OPTION_OTHER) {
  19492.  
  19493.    (void)NNMivget(np,"NNUPAN ",   nnupan,   sizeof(nnupan  ));
  19494.    (void)NNMivget(np,"NNUPRN ",   nnuprn,   sizeof(nnuprn  ));
  19495.    (void)NNMivget(np,"NNUPRA ",   nnupra,   sizeof(nnupra  ));
  19496.    (void)NNMivget(np,"NNMUPDTF ", nnmupdtf, sizeof(nnmupdtf));
  19497.    (void)NNMivget(np,"NNEXTPOW ", nnextpow, sizeof(nnextpow));
  19498.    (void)NNMivget(np,"NNEXTPAP ", nnextpap, sizeof(nnextpap));
  19499.  
  19500.    /* 5 is a "reasonable" default, according to DDI */
  19501.  
  19502.    if      (nnmupdtf[0] == '\0')     np->updatefreq = 5;
  19503.    else if (EQUAL(nnmupdtf, "OFF"))  np->updatefreq = -1;
  19504.    else if (EQUAL(nnmupdtf, "ON"))   np->updatefreq = 0;
  19505.    else                              np->updatefreq = atoi(nnmupdtf);
  19506.  
  19507.    BOOLOPTSET(nnupan,   np->update_adding_newsgroups,    FALSE);
  19508.    BOOLOPTSET(nnuprn,   np->update_rewriting_newsrc,     TRUE);
  19509.    BOOLOPTSET(nnupra,   np->update_retrieving_articles,  TRUE);
  19510.    BOOLOPTSET(nnextpow, np->warn_overwrite,              TRUE);
  19511.    BOOLOPTSET(nnextpap, np->warn_append,                 TRUE);
  19512.  
  19513.    if (!np->update_retrieving_articles) np->updatefreq = -1;
  19514.  
  19515.  }
  19516.  
  19517.  if (which == OPTION_ALL || which == OPTION_VIEW) {
  19518.  
  19519.    (void)NNMivget(np,"NNNGSCR ",  nnngscr,  sizeof(nnngscr ));
  19520.    (void)NNMivget(np,"NNNGCSR ",  nnngcsr,  sizeof(nnngcsr ));
  19521.    (void)NNMivget(np,"NNARSCR ",  nnarscr,  sizeof(nnarscr ));
  19522.    (void)NNMivget(np,"NNARCSR ",  nnarcsr,  sizeof(nnarcsr ));
  19523.    (void)NNMivget(np,"NNARROWS ", nnarrows, sizeof(nnarrows));
  19524.  
  19525.    BOOLOPTSET(nnngscr,  np->newsgroup_autoscroll,        TRUE);
  19526.    BOOLOPTSET(nnngcsr,  np->newsgroup_autocursor,       FALSE);
  19527.    BOOLOPTSET(nnarscr,  np->article_autoscroll,          TRUE);
  19528.    BOOLOPTSET(nnarcsr,  np->article_autocursor,         FALSE);
  19529.  
  19530.    switch (nnarrows[0]) {
  19531.      case  '1':
  19532.      default:     arrows = 1;              break;
  19533.      case  '2':   arrows = 2;              break;
  19534.      case  '3':   arrows = 3;              break;
  19535.    }
  19536.  
  19537.    if (arrows != np->article_rows) {
  19538.      np->article_rows = arrows;
  19539.      np->article_criterion_changed = TRUE;
  19540.    }
  19541.  }
  19542.  
  19543.  return; 
  19544. }
  19545.  
  19546. ./   ADD NAME=NNMSORT,SSI=01080050
  19547.  
  19548.  /********************************************************************/
  19549.  /*                                                                  */
  19550.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19551.  /*                                                                  */
  19552.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  19553.  /*                                                                  */
  19554.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19555.  /* including the implied warranties of merchantability and fitness, */
  19556.  /* are expressly denied.                                            */
  19557.  /*                                                                  */
  19558.  /* Provided this copyright notice is included, this software may    */
  19559.  /* be freely distributed and not offered for sale.                  */
  19560.  /*                                                                  */
  19561.  /* Changes or modifications may be made and used only by the maker  */
  19562.  /* of same, and not further distributed.  Such modifications should */
  19563.  /* be mailed to the author for consideration for addition to the    */
  19564.  /* software and incorporation in subsequent releases.               */
  19565.  /*                                                                  */
  19566.  /********************************************************************/
  19567.  
  19568. #pragma  csect(code,  "NN@SORT ")
  19569. #pragma  csect(static,"NN$SORT ")
  19570. #include "nn.h"
  19571.  
  19572. /****** Compare articles by number. **********************************/
  19573.  
  19574. static int
  19575. compare_articles_by_number(wp1,wp2)
  19576. register const void       *wp1;
  19577. register const void       *wp2;
  19578. {
  19579.  return
  19580.         (VARK2PARTICLE(**(VARK **)wp1))->number
  19581.       - (VARK2PARTICLE(**(VARK **)wp2))->number
  19582.        ; 
  19583. }
  19584.  
  19585. /****** Compare articles by subject. *********************************/
  19586.  
  19587. static int
  19588. compare_articles_by_subject(wp1,wp2)
  19589. register const void       *wp1;
  19590. register const void       *wp2;
  19591. {
  19592.  int answer;
  19593.  
  19594.  answer = strcmp(
  19595.                  (VARK2PARTICLE(**(VARK **)wp1))->csubject,
  19596.                  (VARK2PARTICLE(**(VARK **)wp2))->csubject
  19597.                 );
  19598.  if (answer == 0) return compare_articles_by_number(wp1,wp2);
  19599.  else return answer;
  19600.  
  19601. }
  19602.  
  19603. /****** Make canonical subject. *************************************/
  19604.  
  19605. static char *
  19606. make_canonical_subject(spp,subject)
  19607. char                 **spp;
  19608. char                  *subject;
  19609. {
  19610.  char                 *ip;
  19611.  char                 *op;
  19612.  char                 *rp;
  19613.  int                   re_count;
  19614.  
  19615.  if (!*subject) return "";
  19616.  
  19617.  /* Scan past "re"s and count them up */
  19618.  
  19619.  rp = *spp;
  19620.  
  19621.  re_count = -1;
  19622.  ip = subject - 3;
  19623.  do {
  19624.    ip = ip + 3 + strspn(ip + 3," \t");
  19625.    re_count++;
  19626.  } while (!memcmp(ip,"Re:",3) ||
  19627.           !memcmp(ip,"re:",3) ||
  19628.        /* !memcmp(ip,"rE:",3) || - do you really expect this??? */
  19629.           !memcmp(ip,"RE:",3));
  19630.  
  19631.  /* Copy subject to buffer while lowercasing. Sets op to last nonblank
  19632.     character in buffer. */
  19633.  
  19634.  copy_lowercase_and_strip_trailing(rp,ip,op);
  19635.  
  19636.  /* Hack for prioritizing RE:'s.  Add a byte at the end to put
  19637.   * subjects in order.  e.g.:
  19638.   * Subject: Foo              --> "foo\0"
  19639.   * Subject: Re: Foo          --> "foo\001\0"
  19640.   * Subject: Re: Re: Foo      --> "foo\002\0"
  19641.   *
  19642.   * This algorithm will break if there are more than 255 "RE:"s,
  19643.   * but do you really think that's likely?
  19644.   */
  19645.  
  19646.  if (re_count > 0) {
  19647.    *op = (unsigned char) re_count;
  19648.    op++; 
  19649.  }
  19650.  *op = '\0';
  19651.  
  19652.  *spp = op + 1;   /* Bump buffer pointer past our new end */
  19653.  
  19654.  return rp;
  19655.  
  19656. }
  19657.  
  19658. /****** Sort article table. *****************************************/
  19659.  
  19660. Bool
  19661. NNMsort(np,gp)
  19662. Rstruc nncb         *np;
  19663. Rstruc newsgroup    *gp;
  19664. {
  19665.  Rstruc newsarticle *ap;
  19666.  VARK               *vp;
  19667.  VARK               *vpfirst;
  19668.  VARK               *vplast;
  19669.  VARK              **wp;
  19670.  char               *sortbuf;
  19671.  char               *sp;
  19672.  int                 sortbufsize;
  19673.  int                 count;
  19674.  int                 i;
  19675.  
  19676.  if (!gp->article_vector) return TRUE;
  19677.  
  19678.  if (gp->sort_vector) {
  19679.    FREEMAIN(gp->sort_vector,"sort vector");
  19680.    gp->sort_vector = NULL;
  19681.    gp->sort_count  = 0;
  19682.  }
  19683.  
  19684.  /* Retrieve article titles, read or unread, but ignoring any
  19685.   * subject filtering.
  19686.   */
  19687.  count = NNMrart(np,gp,FALSE,TRUE); /* Retrieve article titles */
  19688.  if (count == 0) return TRUE;
  19689.  
  19690.  GETMAIN(gp->sort_vector, VARK **, count, "sort vector");
  19691.  if (!gp->sort_vector) {
  19692.    CRIT1("There is not enough memory to sort the newsgroup.");
  19693.    return FALSE;
  19694.  }
  19695.  
  19696.  gp->sort_count = count;
  19697.  
  19698.  vpfirst = &GETVARKFIRST(gp);
  19699.  vplast  = &GETVARKLAST(gp);
  19700.  wp = gp->sort_vector;
  19701.  sortbufsize = 0;
  19702.  for (vp = vpfirst; vp <= vplast; vp++) {
  19703.    if (IsEligible(*vp)) {     /* i.e. if NNMrart retrieved it */
  19704.      ap = VARK2PARTICLE(*vp);
  19705.      if (*ap->subject) sortbufsize += strlen(ap->subject) + 1;
  19706.      SetUnknown(*vp);         /* unfudge status as we go */
  19707.      *(wp++) = vp;
  19708.    }
  19709.  }
  19710.  
  19711.  if (sortbufsize > 0) {
  19712.    GETMAIN(sortbuf, char, sortbufsize, "sort-by-subject buffer");
  19713.    if (!sortbuf) {
  19714.      CRIT1("There is not enough memory to sort articles by subject.");
  19715.      FREEMAIN(gp->sort_vector,"sort vector");
  19716.      gp->sort_vector = NULL;
  19717.      gp->sort_count  = 0;
  19718.      return FALSE;
  19719.    }
  19720.  }
  19721.  
  19722.  sp = sortbuf;
  19723.  for (wp = gp->sort_vector, i = gp->sort_count; i > 0; wp++, i--) {
  19724.    ap = VARK2PARTICLE(**wp);
  19725.    ap->csubject = make_canonical_subject(&sp,ap->subject);
  19726.  }
  19727.  
  19728.  qsort(gp->sort_vector, gp->sort_count, sizeof(VARK **),
  19729.        compare_articles_by_subject);
  19730.  
  19731.  /* This isn't strictly necessary as long as no one tries to refer
  19732.   * to ap->csubject outside of this module.
  19733.   *
  19734.  for (wp = gp->sort_vector, i = gp->sort_count; i > 0; wp++, i--) {
  19735.    ap = VARK2PARTICLE(**wp);
  19736.    ap->csubject = NULL;
  19737.  }
  19738.   *
  19739.   */
  19740.  
  19741.  FREEMAIN(sortbuf,"sort-by-subject buffer");
  19742.  
  19743.  return TRUE;
  19744. }
  19745.  
  19746. ./   ADD NAME=NNMSSRVR,SSI=01000016
  19747.  
  19748.  /********************************************************************/
  19749.  /*                                                                  */
  19750.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19751.  /*                                                                  */
  19752.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19753.  /* including the implied warranties of merchantability and fitness, */
  19754.  /* are expressly denied.                                            */
  19755.  /*                                                                  */
  19756.  /* Provided this copyright notice is included, this software may    */
  19757.  /* be freely distributed and not offered for sale.                  */
  19758.  /*                                                                  */
  19759.  /* Changes or modifications may be made and used only by the maker  */
  19760.  /* of same, and not further distributed.  Such modifications should */
  19761.  /* be mailed to the author for consideration for addition to the    */
  19762.  /* software and incorporation in subsequent releases.               */
  19763.  /*                                                                  */
  19764.  /********************************************************************/
  19765.  
  19766. #pragma  csect(code,  "NN@SSRVR")
  19767. #pragma  csect(static,"NN$SSRVR")
  19768. #include "nn.h"
  19769.  
  19770. /****** Start server read. *******************************************/
  19771.  
  19772. void
  19773. NNMssrvr(np)
  19774. Rstruc nncb  *np;
  19775. {
  19776.  
  19777.  np->server_has_something_pending = TRUE;
  19778.  np->server_finished_replying     = FALSE;
  19779.  np->sending_text                 = FALSE;
  19780.  np->something_to_print           = FALSE;
  19781.  np->dont_read                    = FALSE;
  19782.  
  19783.  return; 
  19784.  
  19785. }
  19786.  
  19787. ./   ADD NAME=NNMSTRLC,SSI=01000026
  19788.  
  19789.  /********************************************************************/
  19790.  /*                                                                  */
  19791.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19792.  /*                                                                  */
  19793.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19794.  /* including the implied warranties of merchantability and fitness, */
  19795.  /* are expressly denied.                                            */
  19796.  /*                                                                  */
  19797.  /* Provided this copyright notice is included, this software may    */
  19798.  /* be freely distributed and not offered for sale.                  */
  19799.  /*                                                                  */
  19800.  /* Changes or modifications may be made and used only by the maker  */
  19801.  /* of same, and not further distributed.  Such modifications should */
  19802.  /* be mailed to the author for consideration for addition to the    */
  19803.  /* software and incorporation in subsequent releases.               */
  19804.  /*                                                                  */
  19805.  /********************************************************************/
  19806.  
  19807. #pragma  csect(code,  "NN@STRLC")
  19808. #pragma  csect(static,"NN$STRLC")
  19809. #include "nn.h"
  19810.  
  19811. /****** Case-insensitive string search. ******************************/
  19812.  
  19813.   /* This differs from the Ustrstr function in NNMbbexp in that it only
  19814.    * has to lowercase the "b" argument, not both.  The "a" argument
  19815.    * is assumed to be all lower case already.
  19816.    */
  19817.  
  19818. char *
  19819. NNMstrlc(b,a)
  19820. register char  *b;
  19821. register char  *a;
  19822. {
  19823.  register char *aa;
  19824.  register char *bb;
  19825.  
  19826.  if (!*a) return strchr(b,'\0');
  19827.  
  19828.  for (;;) {
  19829.  
  19830.    while (*b && (*a != tolower(*b))) b++;
  19831.  
  19832.    if (!*b) return NULL;
  19833.  
  19834.    for (aa = a, bb = b;
  19835.         *aa && *bb && (*aa == tolower(*bb));
  19836.         aa++, bb++) ;
  19837.  
  19838.    if (!*aa) return a;
  19839.  
  19840.    b++;
  19841.  }
  19842.  
  19843. }
  19844.  
  19845. ./   ADD NAME=NNMSUMAT,SSI=01000051
  19846.  
  19847.  /********************************************************************/
  19848.  /*                                                                  */
  19849.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19850.  /*                                                                  */
  19851.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19852.  /* including the implied warranties of merchantability and fitness, */
  19853.  /* are expressly denied.                                            */
  19854.  /*                                                                  */
  19855.  /* Provided this copyright notice is included, this software may    */
  19856.  /* be freely distributed and not offered for sale.                  */
  19857.  /*                                                                  */
  19858.  /* Changes or modifications may be made and used only by the maker  */
  19859.  /* of same, and not further distributed.  Such modifications should */
  19860.  /* be mailed to the author for consideration for addition to the    */
  19861.  /* software and incorporation in subsequent releases.               */
  19862.  /*                                                                  */
  19863.  /********************************************************************/
  19864.  
  19865. #pragma  csect(code,  "NN@SUMAT")
  19866. #pragma  csect(static,"NN$SUMAT")
  19867. #include "nn.h"
  19868.  
  19869. /****** Subject matching code. ***************************************/
  19870.  
  19871. Bool
  19872. NNMsumat(a,b)
  19873. char        *a;
  19874. char        *b;
  19875. {
  19876.  char       *cp;
  19877.  char       *c1;
  19878.  char       *c2;
  19879.  char        bracket;
  19880.  char        s1[257];
  19881.  char        s2[257];
  19882.  
  19883.  strncpy(s1,a,256);
  19884.  strncpy(s2,b,256);
  19885.  
  19886.  lowercase_and_strip_trailing_in_place(s1);
  19887.  lowercase_and_strip_trailing_in_place(s2);
  19888.  
  19889.  c1 = skip_whitespace(s1);
  19890.  c2 = skip_whitespace(s2);
  19891.  
  19892.  if (!strcmp(c1,c2)) return TRUE;
  19893.  
  19894.  while (!memcmp(c1,"re:",3)) {
  19895.    c1 = skip_whitespace(c1+3);
  19896.    if (!strcmp(c1,c2)) return TRUE;
  19897.  }
  19898.  while (!memcmp(c2,"re:",3)) {
  19899.    c2 = skip_whitespace(c2+3);
  19900.    if (!strcmp(c1,c2)) return TRUE;
  19901.  }
  19902.  
  19903.  if ((cp=strstr(c1,"(was:" /*)*/ )) ||
  19904.      (cp=strstr(c1,"(was " /*)*/ )) ||
  19905.      (cp=strstr(c1,"[was " /*)*/ )) ||
  19906.      (cp=strstr(c1,"[was:" /*)*/ ))) {
  19907.    switch (*cp) {
  19908.      case '(':  bracket = ')';  break;
  19909.      case '[':  bracket = ']';  break;
  19910.      default:   bracket = '\0'; break;
  19911.    }
  19912.    c1 = skip_whitespace(cp+5);
  19913.    if (!memcmp(c1,"re:",3)) c1 = skip_whitespace(c1+3);
  19914.    if (!strcmp(c1,c2)) return TRUE;
  19915.    cp = c1 + strlen(c1) - 1;
  19916.    if (*cp == bracket) *cp = '\0';
  19917.    if (!strcmp(c1,c2)) return TRUE;
  19918.  }
  19919.  if ((cp=strstr(c2,"(was:" /*)*/ )) ||
  19920.      (cp=strstr(c2,"(was " /*)*/ )) ||
  19921.      (cp=strstr(c2,"[was " /*)*/ )) ||
  19922.      (cp=strstr(c2,"[was:" /*)*/ ))) {
  19923.    switch (*cp) {
  19924.      case '(':  bracket = ')';  break;
  19925.      case '[':  bracket = ']';  break;
  19926.      default:   bracket = '\0'; break;
  19927.    }
  19928.    c2 = skip_whitespace(cp+5);
  19929.    if (!memcmp(c2,"re:",3)) c2 = skip_whitespace(c2+3);
  19930.    if (!strcmp(c1,c2)) return TRUE;
  19931.    cp = c2 + strlen(c2) - 1;
  19932.    if (*cp == bracket) *cp = '\0';
  19933.    if (!strcmp(c1,c2)) return TRUE;
  19934.  }
  19935.  
  19936.  if (!strcmp(c1,c2)) return TRUE;
  19937.  
  19938.  return FALSE;
  19939.  
  19940. }
  19941.  
  19942. ./   ADD NAME=NNMTSO,SSI=01000006
  19943.  
  19944.  /********************************************************************/
  19945.  /*                                                                  */
  19946.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  19947.  /*                                                                  */
  19948.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  19949.  /* including the implied warranties of merchantability and fitness, */
  19950.  /* are expressly denied.                                            */
  19951.  /*                                                                  */
  19952.  /* Provided this copyright notice is included, this software may    */
  19953.  /* be freely distributed and not offered for sale.                  */
  19954.  /*                                                                  */
  19955.  /* Changes or modifications may be made and used only by the maker  */
  19956.  /* of same, and not further distributed.  Such modifications should */
  19957.  /* be mailed to the author for consideration for addition to the    */
  19958.  /* software and incorporation in subsequent releases.               */
  19959.  /*                                                                  */
  19960.  /********************************************************************/
  19961.  
  19962.  /********************************************************************/
  19963.  /*                                                                  */
  19964.  /* Thanks to Michael Van Norman for this code.                      */
  19965.  /*                                                                  */
  19966.  /********************************************************************/
  19967.  
  19968. #pragma  csect(code,  "NN@TSO  ")
  19969. #pragma  csect(static,"NN$TSO  ")
  19970. #include "nn.h"
  19971.  
  19972. #pragma linkage(ikjeftsr,OS)
  19973.  
  19974. #define _IKJEFTSR_FLAGS_AUTH        0x00000000
  19975. #define _IKJEFTSR_FLAGS_COMMAND     0x00000001
  19976. #define _IKJEFTSR_FLAGS_DUMP        0x00000100
  19977. #define _IKJEFTSR_FLAGS_NODUMP      0x00000000
  19978. #define _IKJEFTSR_FLAGS_PROGRAM     0x00000002
  19979. #define _IKJEFTSR_FLAGS_UNAUTH      0x00010000
  19980.  
  19981. /****** Issue TSO command. *******************************************/
  19982.  
  19983. int
  19984. NNMtso(command)
  19985. char        *command;
  19986. {
  19987.  int         flags         = _IKJEFTSR_FLAGS_COMMAND +
  19988.                              _IKJEFTSR_FLAGS_UNAUTH;
  19989.  int         commandLength = strlen(command);
  19990.  int         rc            = 0;
  19991.  int         returnCode    = 0;
  19992.  int         reasonCode    = 0;
  19993.  int         abendCode     = 0;
  19994.  
  19995.  static int (*ikjeftsr)() = NULL;
  19996.  
  19997.  if (!ikjeftsr) {
  19998.    /*
  19999.    ikjeftsr = (int (*)())fetch("ikjeftsr");
  20000.    if (!ikjeftsr) {
  20001.     */
  20002.      /* #pragma linkage( tsoServiceFacility, OS )
  20003.       * int (*tsoServiceFacility)( int *, char *, int *,
  20004.       *                            int *, int *, int * );
  20005.       */ 
  20006.      int tsoEntryAddress;
  20007.  
  20008.      tsoEntryAddress = 0x00000010;    /* Address of CVT */
  20009.      tsoEntryAddress = *(int *)(tsoEntryAddress);
  20010.      tsoEntryAddress += 0x9C;/*       /* Offset of TVT in CVT */
  20011.      tsoEntryAddress = *(int *)(tsoEntryAddress);
  20012.      tsoEntryAddress += 0x10;/*       /* TSVTASF-TSVT (from IKJTSVT) */
  20013.      tsoEntryAddress = *(int *)(tsoEntryAddress);
  20014.      ikjeftsr = (int (*)())(tsoEntryAddress);
  20015.    /*
  20016.    }
  20017.    */
  20018.  }
  20019.  
  20020.  if (!ikjeftsr) {
  20021.    fprintf(stderr,
  20022.            "Cannot execute TSO commands, can't fetch IKJEFTSR.\n");
  20023.    return -2;
  20024.  }
  20025.  
  20026.  rc = (*ikjeftsr)(&flags, command, &commandLength,
  20027.                           &returnCode, &reasonCode,
  20028.                           (int *)((int)(&abendCode) | 0x80000000));
  20029.  
  20030.  if (rc != 0) {
  20031.    if (rc > 4) {
  20032.      fprintf(stderr,"Command failed:%s\n",command);
  20033.      if (rc == 20 && reasonCode == 40)
  20034.           fprintf(stderr,"Command was not found.\n");
  20035.      else fprintf(stderr,
  20036.              "rc=%d,returncode=%d,reasoncode=%d,abendcode=%8.8x\n",
  20037.              rc, returnCode, reasonCode, abendCode);
  20038.    }
  20039.    if (abendCode != 0) rc = -1;
  20040.    else rc = returnCode;
  20041.  }
  20042.  
  20043.  return rc;
  20044. }
  20045.  
  20046. ./   ADD NAME=NNMUNALC,SSI=01010053
  20047.  
  20048.  /********************************************************************/
  20049.  /*                                                                  */
  20050.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  20051.  /*                                                                  */
  20052.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20053.  /* including the implied warranties of merchantability and fitness, */
  20054.  /* are expressly denied.                                            */
  20055.  /*                                                                  */
  20056.  /* Provided this copyright notice is included, this software may    */
  20057.  /* be freely distributed and not offered for sale.                  */
  20058.  /*                                                                  */
  20059.  /* Changes or modifications may be made and used only by the maker  */
  20060.  /* of same, and not further distributed.  Such modifications should */
  20061.  /* be mailed to the author for consideration for addition to the    */
  20062.  /* software and incorporation in subsequent releases.               */
  20063.  /*                                                                  */
  20064.  /********************************************************************/
  20065.  
  20066. #pragma  csect(code,  "NN@UNALC")
  20067. #pragma  csect(static,"NN$UNALC")
  20068. #include "nn.h"
  20069.  
  20070. /****** Unallocate a data set. ***************************************/
  20071.  
  20072. Bool
  20073. NNMunalc(ddname)
  20074. char         *ddname;
  20075. {
  20076.  __S99parms   stuff99;   /* The manual has it wrong.  No "struct". */
  20077.  int          rc;
  20078.  TEXTUNIT    *tu [2];
  20079.  TEXTUNIT     tu_ddn;
  20080.  TEXTUNIT     tu_una;
  20081.  
  20082.  if (!ddname ||
  20083.      !*ddname) return TRUE;   /* if no ddname to free, do nothing */
  20084.  
  20085.  memset((char *)&stuff99,0,sizeof(__S99parms));
  20086.  
  20087.  stuff99.__S99RBLN   = 20;
  20088.  stuff99.__S99VERB   = S99VRBUN;
  20089.  stuff99.__S99FLAG1  = 0;
  20090.  stuff99.__S99ERROR  = 0;
  20091.  stuff99.__S99INFO   = 0;
  20092.  stuff99.__S99TXTPP  = tu;
  20093.  stuff99.__S99FLAG2  = 0;
  20094.  
  20095.  tu[0] = &tu_ddn;
  20096.  tu[1] = &tu_una;
  20097.  *(int *)&tu[1] |= 0x80000000;
  20098.  
  20099.  tu_ddn.key     = DUNDDNAM;
  20100.  tu_ddn.num     = 1;
  20101.  tu_ddn.ent.len = strlen(ddname);
  20102.  copy_uppercase(tu_ddn.ent.prm,ddname);
  20103.  
  20104.  tu_una.key     = DUNUNALC;
  20105.  tu_una.num     = 0;
  20106.  
  20107.  rc = svc99(&stuff99);
  20108.  
  20109.  if (rc == 0) return TRUE;
  20110.  else if (stuff99.__S99ERROR == 0x0438) /* not freed, is not allocated*/
  20111.          return TRUE;
  20112.  else {
  20113.    NNMdfail(rc,&stuff99);
  20114.    return FALSE;
  20115.  }
  20116. }
  20117.  
  20118. ./   ADD NAME=NNMUPDT,SSI=01000017
  20119.  
  20120.  /********************************************************************/
  20121.  /*                                                                  */
  20122.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  20123.  /*                                                                  */
  20124.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  20125.  /*                                                                  */
  20126.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20127.  /* including the implied warranties of merchantability and fitness, */
  20128.  /* are expressly denied.                                            */
  20129.  /*                                                                  */
  20130.  /* Provided this copyright notice is included, this software may    */
  20131.  /* be freely distributed and not offered for sale.                  */
  20132.  /*                                                                  */
  20133.  /* Changes or modifications may be made and used only by the maker  */
  20134.  /* of same, and not further distributed.  Such modifications should */
  20135.  /* be mailed to the author for consideration for addition to the    */
  20136.  /* software and incorporation in subsequent releases.               */
  20137.  /*                                                                  */
  20138.  /********************************************************************/
  20139.  
  20140. #pragma  csect(code,  "NN@UPDT ")
  20141. #pragma  csect(static,"NN$UPDT ")
  20142. #include "nn.h"
  20143.  
  20144. /****** Update the screen as frequently as desired. ******************/
  20145.  
  20146. void
  20147. NNMupdt(np,cdp,screen)
  20148. Rstruc nncb           *np;
  20149. struct countdown      *cdp;
  20150. char                  *screen;
  20151. {
  20152.   int                  pct;
  20153.   int                  barsize;
  20154.   int                  l;
  20155.   int                  timediff;
  20156.   int                  h;
  20157.   int                  m;
  20158.   int                  s;
  20159.   time_t               thistime;
  20160.   char                 nnmbar[62];
  20161.   char                 nnmestm[9];
  20162.   char                 zhilite[9];
  20163.   char                 temp[8];
  20164.   char                 display_string[24];
  20165.  
  20166.   if (!cdp || !cdp->do_update || np->batch_mode) return;
  20167.  
  20168.   time(&thistime);
  20169.  
  20170.   if (cdp->done == 0) {
  20171.     if (cdp->to_do == 0) return;
  20172.     if (np->barchar == '\0') {
  20173.       (void)NNMivget(np,"ZHILITE ",zhilite,sizeof(zhilite));
  20174.       if (zhilite[0] == 'Y') np->barchar = ' ';
  20175.       else                   np->barchar = '@';
  20176.     }
  20177.     timediff = -1;                 /* don't display on initial call */
  20178.     np->lasttime = thistime;
  20179.     np->firstime = thistime;
  20180.     memset(nnmestm,' ',sizeof(nnmestm));
  20181.     (void)NNMivput(np, "NNMESTM ", nnmestm, 0);
  20182.   }
  20183.   else { 
  20184.     timediff = (int)difftime(thistime, np->lasttime);
  20185.   }
  20186.  
  20187.   if (timediff >= np->updatefreq) {
  20188.     memset(nnmbar,' ',sizeof(nnmbar));
  20189.     nnmbar[0] = '^';
  20190.     if (cdp->to_do < 0) {
  20191.       pct = 0;
  20192.       barsize = 1;
  20193.     }
  20194.     else {
  20195.       if (cdp->to_do < cdp->done) cdp->to_do = cdp->done;
  20196.       pct = cdp->done * 100 / cdp->to_do;
  20197.       barsize = pct * (sizeof(nnmbar) - 2) / 100 + 1;
  20198.     }
  20199.     memset(nnmbar+1, np->barchar, barsize-1);
  20200.     nnmbar[barsize++] = '/';
  20201.  
  20202. #if 1
  20203.  
  20204.     /* This code adds the number of currently processed items to the  */
  20205.     /* right of the bar until it won't fit anymore, then puts it      */
  20206.     /* inside the bar.                                                */
  20207.  
  20208.     l = sprintf(temp, "%d", cdp->done);
  20209.     if (barsize + l < sizeof(nnmbar)) {
  20210.       memcpy(&nnmbar[barsize], temp, l);
  20211.     }
  20212.     else {
  20213.       memcpy(&nnmbar[barsize-l-3], temp, l);
  20214.       if (np->barchar != ' ') {
  20215.         nnmbar[barsize-l-4] = ' ';
  20216.         nnmbar[barsize-3]   = ' ';
  20217.       }
  20218.     }
  20219.  
  20220. #else
  20221.  
  20222.     /* This code adds the number of currently processed items to the  */
  20223.     /* right of the bar until it will fit inside, then puts it there. */
  20224.  
  20225.     l = sprintf(temp, "%d", cdp->done);
  20226.     if (barsize - 4 < l + 2) {
  20227.       memcpy(&nnmbar[barsize], temp, l);
  20228.     }
  20229.     else {
  20230.       memcpy(&nnmbar[barsize-l-3], temp, l);
  20231.       if (np->barchar != ' ') {
  20232.         nnmbar[barsize-l-4] = ' ';
  20233.         nnmbar[barsize-3]   = ' ';
  20234.       }
  20235.     }
  20236.  
  20237. #endif
  20238.  
  20239.     (void)NNMivput(np, "NNMBAR ",nnmbar,sizeof(nnmbar));
  20240.  
  20241.     l = sprintf(temp, "%d", cdp->to_do);
  20242.     (void)NNMivput(np, "NNMCOUNT", temp, l);
  20243.  
  20244.     s = (cdp->to_do - cdp->done) * difftime(thistime, np->firstime)
  20245.         / cdp->done;
  20246.     if (s > 0) {
  20247.       m = s / 60;  s = s % 60;
  20248.       h = m / 60;  m = m % 60;
  20249.       sprintf(nnmestm, "%2.2d:%2.2d:%2.2d", h, m, s);
  20250.       (void)NNMivput(np, "NNMESTM ", nnmestm, sizeof(nnmestm) - 1);
  20251.     }
  20252.  
  20253.     sprintf(display_string, "DISPLAY PANEL(%s)", screen);
  20254.     (void)NNMispf(np, "CONTROL DISPLAY LOCK");
  20255.     (void)NNMispf(np, display_string);
  20256.     np->lasttime = thistime;
  20257.   }
  20258.  
  20259.   cdp->done++;
  20260.  
  20261.   return;
  20262.  
  20263. }
  20264.  
  20265. ./   ADD NAME=NNMVAR,SSI=01250015
  20266.  
  20267.  /********************************************************************/
  20268.  /*                                                                  */
  20269.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  20270.  /*                                                                  */
  20271.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  20272.  /*                                                                  */
  20273.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20274.  /* including the implied warranties of merchantability and fitness, */
  20275.  /* are expressly denied.                                            */
  20276.  /*                                                                  */
  20277.  /* Provided this copyright notice is included, this software may    */
  20278.  /* be freely distributed and not offered for sale.                  */
  20279.  /*                                                                  */
  20280.  /* Changes or modifications may be made and used only by the maker  */
  20281.  /* of same, and not further distributed.  Such modifications should */
  20282.  /* be mailed to the author for consideration for addition to the    */
  20283.  /* software and incorporation in subsequent releases.               */
  20284.  /*                                                                  */
  20285.  /********************************************************************/
  20286.  
  20287. #pragma  csect(code,  "NN@VAR  ")
  20288. #pragma  csect(static,"NN$VAR  ")
  20289. #include "nn.h"
  20290.  
  20291. #define ROWCPY(A,B,C) {\
  20292.                        name_length = strlen(B); \
  20293.                        if (name_length > C) name_length = C; \
  20294.                        memcpy(&rowp[A], B, name_length); \
  20295.                       }
  20296.  
  20297. struct ntdynarray {
  20298.                    struct newsarticle    *article;
  20299.                    VARK                 **sortvark;
  20300.                    int                    number;
  20301.                    char                   numstr [6];
  20302.                   };
  20303.  
  20304. /****** Format screen line. ******************************************/
  20305.  
  20306. static void
  20307. format_screen_line(ap,vp,ndp,wp)
  20308. Rstruc newsarticle    *ap;
  20309. VARK                  *vp;
  20310. Rstruc ntdynarray     *ndp;
  20311. VARK                 **wp;
  20312. {
  20313.  ndp->sortvark = wp;
  20314.  ndp->article  = ap;
  20315.  ndp->number   = ap->number;
  20316.  sprintf(ndp->numstr, "%5d", ndp->number);
  20317.  if (ap->action == NO_ACTION) {
  20318.   if (IsRead(*vp)) ap->action = READ;
  20319.   else             ap->action = UNREAD;
  20320.  }
  20321.  return; 
  20322. }
  20323.  
  20324. /****** View articles. ***********************************************/
  20325.  
  20326. static Bool
  20327. view_articles(np,gp,dynarray,nntdyna,depth,dynsize)
  20328. Rstruc nncb           *np;
  20329. Rstruc newsgroup      *gp;
  20330. struct ntdynarray     *dynarray;
  20331. char                  *nntdyna;
  20332. int                    depth;
  20333. int                    dynsize;
  20334. {
  20335.  struct newsarticle   *ap;
  20336.  Rstruc ntdynarray    *ndp;
  20337.  Rstruc tabledesc     *tdp;
  20338.  Rstruc seldesc       *sdp;
  20339.  Rstruc cmddesc       *cdp;
  20340.  struct ntdynarray    *ntdynarray_start;
  20341.  struct ntdynarray    *ntdynarray_end;
  20342.  char                 *cp;
  20343.  char                 *rowp;
  20344.  char                 *act;
  20345.  VARK                 *vp;
  20346.  VARK                 *vpfirst;
  20347.  VARK                 *vplast;
  20348.  VARK                **wp;
  20349.  VARK                **wpfirst;
  20350.  VARK                **wplast;
  20351.  VARK                **save_top_sorted_article;
  20352.  int                   save_top_article;
  20353.  int                   display_total;
  20354.  int                   command_index;
  20355.  int                   prc;
  20356.  int                   nntlvl;
  20357.  int                   articles_per_screen;
  20358.  int                   scroll;
  20359.  int                   zscrolln;
  20360.  int                   rowincr;
  20361.  int                   rowbump;
  20362.  int                   actlen;
  20363.  int                   anum;
  20364.  int                   artcursor;
  20365.  int                   last_article_selected;
  20366.  short                 name_length;
  20367.  Bool                  is_max;
  20368.  Bool                  is_scroll_word;
  20369.  Bool                  rebuild_dynamic_array;
  20370.  Bool                  selection_processed_ok;
  20371.  Bool                  command_processed_ok;
  20372.  char                  aattr;
  20373.  char                  sel;
  20374.  struct countdown      cd;
  20375.  char                  tcmd        [72];
  20376.  char                  nnthead     [81];
  20377.  char                  nntcsr      [12];
  20378.  char                  command      [COMMANDSIZE];
  20379.  char                  zverb        [9];
  20380.  char                  zscrolla     [9];
  20381.  char                  rowmessage  [81];
  20382.  
  20383.  ntdynarray_start        = dynarray;
  20384.  rebuild_dynamic_array   = TRUE;
  20385.  scroll                  = 0;
  20386.  artcursor               = 0;
  20387.  last_article_selected   = -1;
  20388.  save_top_article        = 0;
  20389.  save_top_sorted_article = NULL;
  20390.  tdp = np->display_table_vector->article_display_table;
  20391.  strcpy(tcmd,"");
  20392.  strcpy(np->article_only_string,"");
  20393.  
  20394.  cd.do_update = (np->updatefreq >= 0);
  20395.  cd.done      = 0;
  20396.  cd.to_do     = -1;
  20397.  
  20398.  /* Loop displaying article titles until END. */
  20399.  
  20400.  do {
  20401.  
  20402.   /* The very first time, all articles have a not-known-yet status.
  20403.    * The normal article collections set knownness on the fly.
  20404.    * When the article criterion changes (e.g. ONLY command),
  20405.    * all articles are set to unknown.  This could also be done
  20406.    * in processing for the ONLY command itself.
  20407.    * If status has been changed (read->unread or vice versa),
  20408.    * alter it here.  But do not change it if the status is read
  20409.    * and the displayed status has been set to one of those
  20410.    * funny values like "Extracted".
  20411.    * This is needed because the newsgroup mark and unmark
  20412.    * operations do not go through the ap actions.
  20413.    */
  20414.  
  20415.    if (np->article_criterion_changed) {
  20416.      if (gp->sort_vector) (void)NNMsort(np,gp);
  20417.      np->article_criterion_changed = FALSE;
  20418.      rebuild_dynamic_array = TRUE;
  20419.      if (gp->article_vector) {
  20420.        vpfirst = &GETVARKFIRST(gp);
  20421.        vplast  = &GETVARKLAST(gp);
  20422.        for (vp = vpfirst; vp <= vplast; vp++) {
  20423.          SetUnknown(*vp);
  20424.          if (IsPresent(*vp) && (ap=VARK2PARTICLE(*vp))) {
  20425.            if (IsRead(*vp)) {
  20426.              if (ap->action == UNREAD
  20427.               || ap->action == MISSING
  20428.               || ap->action == ERROR
  20429.               || ap->action == NO_ACTION) ap->action = READ;
  20430.              else;
  20431.            }
  20432.            else ap->action = UNREAD;
  20433.          }
  20434.        } 
  20435.      }
  20436.    } /* end if article criterion changed */
  20437.  
  20438.    /*
  20439.     * If necessary, rebuild the array of newsarticle pointers.
  20440.     */
  20441.  
  20442.    if (rebuild_dynamic_array) {
  20443.      rebuild_dynamic_array = FALSE;
  20444.      rowincr               = np->article_rows;
  20445.      if (rowincr < 1) rowincr = 1;
  20446.      rowbump               = 80 * rowincr;
  20447.      articles_per_screen   = (depth-1)/rowincr + 1;
  20448.      cd.do_update          = (np->updatefreq >= 0);
  20449.      cd.done               = 0;
  20450.      cd.to_do              = articles_per_screen;
  20451.      display_total         = articles_per_screen;
  20452.      ndp                   = ntdynarray_start;
  20453.  
  20454.      /* Process scroll, collecting (abs(scroll)) articles
  20455.       * until the new top-of-display article is found.  Logic:
  20456.       * If top article is logically past end, then OK.
  20457.       * If top article is not eligible, move back up until we find
  20458.       * an eligible one.
  20459.       * If top article is first but still not eligible, move down
  20460.       * until we find an eligible one.
  20461.       * Then collect enough articles to fill the screen.
  20462.       */ 
  20463.  
  20464.      if (gp->sort_vector) {
  20465.  
  20466.        wpfirst = gp->sort_vector;
  20467.        wplast  = gp->sort_vector + gp->sort_count;
  20468.  
  20469.        wp = np->top_sorted_article;
  20470.  
  20471.        if (wp < wplast) {
  20472.          for (; wp >= wpfirst; wp--)
  20473.              if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) break;
  20474.        } 
  20475.  
  20476.        if (wp < wpfirst) {
  20477.          for (wp = wpfirst; wp < wplast; wp++)
  20478.              if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) break;
  20479.        } 
  20480.  
  20481.        if (scroll > 0) {
  20482.          while (scroll > 0 && ++wp < wplast) {
  20483.            if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) scroll--;
  20484.          }
  20485.        } 
  20486.        else if (scroll < 0) {
  20487.          while (scroll < 0 && --wp >= wpfirst) {
  20488.            if (NNMcar(np,gp,0,*wp,NULL,&cd,RETRIEVE)) scroll++;
  20489.          }
  20490.          if (wp < wpfirst) wp = wpfirst;
  20491.        } 
  20492.        np->top_sorted_article = wp;
  20493.  
  20494.        for (; display_total > 0 && wp < wplast; wp++) {
  20495.          if (NNMcar(np,gp,0,*wp,&ap,&cd,RETRIEVE)) {
  20496.            format_screen_line(ap,*wp,ndp,wp);
  20497.            display_total--;
  20498.            ndp++;
  20499.          }
  20500.        } 
  20501.        ntdynarray_end = ndp;
  20502.  
  20503.      }
  20504.  
  20505.      else if (gp->article_vector) { /* not sorted */
  20506.  
  20507.        anum = np->top_article;
  20508.  
  20509.        if (anum <= gp->vector_last) {
  20510.          for (; anum >= gp->vector_first; anum--)
  20511.              if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) break;
  20512.        } 
  20513.  
  20514.        if (anum < gp->vector_first) {
  20515.          for (anum = gp->vector_first; anum <= gp->vector_last; anum++)
  20516.              if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) break;
  20517.        } 
  20518.  
  20519.        if (scroll > 0) {
  20520.          while (scroll > 0 && ++anum <= gp->vector_last) {
  20521.            if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) scroll--;
  20522.          }
  20523.        } 
  20524.        else if (scroll < 0) {
  20525.          while (scroll < 0 && --anum >= gp->vector_first) {
  20526.            if (NNMcar(np,gp,anum,NULL,NULL,&cd,RETRIEVE)) scroll++;
  20527.          }
  20528.          if (anum < gp->vector_first) anum = gp->vector_first;
  20529.        } 
  20530.        np->top_article = anum;
  20531.  
  20532.        for (; display_total > 0 && anum <= gp->vector_last; anum++) {
  20533.          if (NNMcar(np,gp,anum,NULL,&ap,&cd,RETRIEVE)) {
  20534.            vp = &GETVARK(gp,anum);
  20535.            format_screen_line(ap,vp,ndp,NULL);
  20536.            display_total--;
  20537.            ndp++;
  20538.          }
  20539.        } 
  20540.        ntdynarray_end = ndp;
  20541.  
  20542.      } /* end not sorted */
  20543.  
  20544.      else { /* no article vector */
  20545.  
  20546.        ntdynarray_end = ndp;
  20547.        np->top_article = 0;
  20548.  
  20549.      }
  20550.  
  20551.    } /* end if rebuild_dynamic_array */
  20552.  
  20553.    save_top_article = np->top_article;
  20554.    save_top_sorted_article = np->top_sorted_article;
  20555.    artcursor = 0;
  20556.  
  20557.    /* Fill dynamic area with data for groups satisfying criterion. */
  20558.  
  20559.    memset(nntdyna, ' ', dynsize);
  20560.  
  20561.    for (ndp = ntdynarray_start, rowp = nntdyna;
  20562.         ndp < ntdynarray_end;
  20563.         ndp++) {
  20564.      ap = ndp->article;
  20565.      if (np->article_autocursor
  20566.       && ndp->number == last_article_selected) {
  20567.        artcursor = rowp + 2 - nntdyna;
  20568.      }
  20569.      rowp[ 0]        = DATAIN_HIGH;     /* selection code attribute */
  20570.      rowp[ 1]        = ' ';             /* selection code field     */
  20571.      rowp[ 2]        = DATAOUT_BLUE;    /* article number attribute */
  20572.      memcpy(&rowp[ 3], ndp->numstr, 5); /* article number           */
  20573.      rowp[ 8]        = DATAOUT_GREEN;   /* article title attribute  */
  20574.      ROWCPY(9,ap->subject,60);          /* article title            */
  20575.  
  20576.      switch (ap->action) {
  20577.        case NO_ACTION: act = "No action"; aattr = DATAOUT_TURQ;   break;
  20578.        case READ:      act = "Read   "  ; aattr = DATAOUT_BLUE;   break;
  20579.        case RETRIEVED: act = "Retrieved"; aattr = DATAOUT_BLUE;   break;
  20580.        case EXTRACTED: act = "Extracted"; aattr = DATAOUT_BLUE;   break;
  20581.        case PRINTED:   act = "Printed"  ; aattr = DATAOUT_BLUE;   break;
  20582.        case UNREAD:    act = "Unread "  ; aattr = DATAOUT_YELLOW; break;
  20583.        case MISSING:   act = "Missing"  ; aattr = DATAOUT_TURQ;   break;
  20584.        case ERROR:     act = "Error  "  ; aattr = DATAOUT_TURQ;   break;
  20585.        case CANCELLED: act = "Cancelled"; aattr = DATAOUT_BLUE;   break;
  20586.        default:        act = "???????"  , aattr = DATAOUT_TURQ;   break;
  20587.      }
  20588.      actlen = strlen(act);
  20589.      memcpy(&rowp[68-actlen],act,actlen);
  20590.      rowp[68-actlen-1] = aattr;
  20591.  
  20592.      if (rowincr == 1) {
  20593.        rowp[68] = DATAOUT_GREEN;           /* article date attribute */
  20594.        ROWCPY(69,ap->date,11);                      /* article date  */
  20595.      }
  20596.      else {
  20597.        memset(&rowp[68],' ',12);
  20598.      }
  20599.  
  20600.      if ((rowp+=80) >= nntdyna + dynsize) break;
  20601.      if (rowincr >= 2) {
  20602.        rowp[0] = DATAOUT_GREEN;          /* article author attribute */
  20603.        ROWCPY(9,ap->from,58);                    /* article author   */
  20604.        rowp[59] = DATAOUT_GREEN;           /* article date attribute */
  20605.        ROWCPY(60,ap->date,20);                      /* article date  */
  20606.        if ((rowp+=80) >= nntdyna + dynsize) break;
  20607.        if (rowincr >= 3) {
  20608.          rowp[0] = DATAOUT_BLUE;
  20609.          ROWCPY(9,ap->message_id,70);
  20610.          if ((rowp+=80) >= nntdyna + dynsize) break;
  20611.        } 
  20612.      }
  20613.    } /* end for */
  20614.  
  20615.    if (rowp < nntdyna + dynsize) {
  20616.      rowp[0] = DATAOUT_HIGH;
  20617.      memset(&rowp[1], '-',79);
  20618.    }
  20619.  
  20620.  /* Format the heading line for the title display.
  20621.   * Row message is "Range mmmm-nnnn", not "m-n of p", because
  20622.   * we don't always know if we can get to all the articles.
  20623.   */
  20624.  
  20625.    if (!gp->article_vector) strcpy(rowmessage, "");
  20626.    else sprintf(rowmessage, " Range %d-%d",
  20627.                             gp->vector_first, gp->vector_last);
  20628.  
  20629.    memset(nnthead, '-', 80);
  20630.    *(nnthead+80) = '\0';
  20631.    strcpy(nnthead, "Newsgroup: ");
  20632.    name_length = strlen(gp->name);
  20633.    if (name_length > 40) name_length = 40;
  20634.    strncat(nnthead, gp->name, name_length);
  20635.    *(strchr(nnthead,'\0')) = ' ';
  20636.    strcpy(nnthead + 79 - strlen(rowmessage), rowmessage);
  20637.  
  20638.    if (artcursor > 0) {
  20639.      sprintf(nntcsr,"%d",artcursor);
  20640.      (void)NNMivput(np,"NNTCSR ", nntcsr, -1);
  20641.    }
  20642.    else {
  20643.      (void)NNMivput(np,"NNTCSR ", "0", 1);
  20644.    }
  20645.  
  20646.    (void)NNMivput(np,"NNTCMD " , tcmd,    -1);
  20647.    (void)NNMivput(np,"NNTHEAD ", nnthead, -1);
  20648.    (void)NNMivput(np,"NNTDYNA ", nntdyna, dynsize);
  20649.    (void)NNMivput(np,"YRFIND "  ,"ALIAS FIND",-1);
  20650.  
  20651.    prc = NNMdispl(np,"NNMDAR  ");
  20652.    if (prc > 8) break;
  20653.  
  20654.    (void)NNMivput(np,"YRFIND "  ,"",-1);
  20655.    (void)NNMivget(np,"NNTDYNA " , nntdyna,  dynsize);
  20656.    (void)NNMivget(np,"ZVERB "   , zverb,    sizeof(zverb));
  20657.    (void)NNMivget(np,"ZSCROLLA ", zscrolla, sizeof(zscrolla));
  20658.    zscrolln = NNMiget(np,"ZSCROLLN ");
  20659.    nntlvl   = NNMiget(np,"NNTLVL ");
  20660.    scroll   = 0;
  20661.  
  20662.    /* Process selections. */
  20663.  
  20664.    save_top_article = np->top_article;
  20665.    save_top_sorted_article = np->top_sorted_article;
  20666.    np->top_article = 0;
  20667.    np->top_sorted_article = NULL;
  20668.    last_article_selected = -1;
  20669.  
  20670.    for (ndp = ntdynarray_start, rowp = nntdyna;
  20671.         ndp < ntdynarray_end && !np->quit;
  20672.         ndp++,                  rowp += rowbump) {
  20673.      sel = toupper(rowp[1]);
  20674.      if (sel == ' ') continue;
  20675.      for (sdp = tdp->first_seldesc; sdp->selection_code != ' '; sdp++) {
  20676.        if (sel == sdp->selection_code) {
  20677.          ap = ndp->article;
  20678.          np->current_sortvark = ndp->sortvark;
  20679.          selection_processed_ok = (sdp->selection_processor)(np,ap);
  20680.          last_article_selected = ap->number;
  20681.          sdp = NULL;
  20682.          break;
  20683.        } 
  20684.      }
  20685.      if (sdp) {
  20686.        ERR1("Unknown selection code.  Type one of the listed codes.");
  20687.        selection_processed_ok = FALSE;
  20688.      }
  20689.    }
  20690.  
  20691.    if (np->quit) break;
  20692.  
  20693.    if (np->top_article != 0 && np->article_autocursor)
  20694.        last_article_selected = np->top_article;
  20695.    if (np->top_article == 0 || !np->article_autoscroll)
  20696.        np->top_article = save_top_article;
  20697.    if (np->top_sorted_article == NULL || !np->article_autoscroll)
  20698.        np->top_sorted_article = save_top_sorted_article;
  20699.  
  20700.    /* Process command if any. */
  20701.  
  20702.    strcpy(tcmd,"");
  20703.  
  20704.    (void)NNMivget(np,tdp->command_variable,tcmd,sizeof(tcmd));
  20705.  
  20706.    if (strcmp(tcmd,"") != 0) {
  20707.  
  20708.      last_article_selected = -1;
  20709.      memset(command,' ',COMMANDSIZE);
  20710.      command_index = 0;
  20711.      for (cp = tcmd; *cp && !isspace(*cp); cp++) {
  20712.        if (cp >= tcmd+COMMANDSIZE) {
  20713.          ERR1("Unknown command name.");
  20714.          command_processed_ok = FALSE;
  20715.        } 
  20716.        command[command_index++] = toupper(*cp);
  20717.      }
  20718.      while (*cp && isspace(*cp)) cp++;
  20719.  
  20720.      for (cdp = tdp->first_cmddesc; *cdp->command_name != ' '; cdp++) {
  20721.        if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  20722.          command_processed_ok = (cdp->command_processor)(np,gp,cp);
  20723.          cdp = NULL;
  20724.          break;
  20725.        } 
  20726.      }
  20727.      if (cdp) {
  20728.        for (cdp=tdp->next_cmddesc; *cdp->command_name != ' '; cdp++) {
  20729.          if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  20730.            command_processed_ok = (cdp->command_processor)(np,gp,cp);
  20731.            cdp = NULL;
  20732.            break;
  20733.          }
  20734.        } 
  20735.      }
  20736.      if (cdp) {
  20737.        ERR1("Unknown command name.");
  20738.        command_processed_ok = FALSE;
  20739.      }
  20740.  
  20741.      if (command_processed_ok) strcpy(tcmd,"");
  20742.  
  20743.    }
  20744.  
  20745.    if (np->quit) break;
  20746.  
  20747.    if (np->top_article != save_top_article
  20748.     || np->top_sorted_article != save_top_sorted_article)
  20749.        rebuild_dynamic_array = TRUE;
  20750.  
  20751.    /* Process scroll request if any. */
  20752.  
  20753.    switch (zscrolla[0]) {
  20754.      case 'P':
  20755.      case 'H':
  20756.      case 'C':
  20757.      case 'D':  is_max = FALSE;
  20758.                 is_scroll_word = TRUE;
  20759.                 break;
  20760.      case 'M':  is_max = TRUE;
  20761.                 break;
  20762.      default:   is_max = FALSE;
  20763.                 is_scroll_word = FALSE;
  20764.                 break;
  20765.    }
  20766.  
  20767.    if      (EQUAL(zverb,"DOWN")) {
  20768.      if (is_max)         {
  20769.                           np->top_article = gp->vector_last;
  20770.                           np->top_sorted_article = wplast - 1;
  20771.                           scroll = -((nntlvl-1)/np->article_rows);
  20772.                          }
  20773.      else
  20774.      if (is_scroll_word)  scroll = zscrolln/rowincr;
  20775.      else                 scroll = zscrolln;
  20776.    }
  20777.    else if (EQUAL(zverb,"UP")) {
  20778.      if (is_max)         {
  20779.                           np->top_article = gp->vector_first;
  20780.                           np->top_sorted_article = wpfirst;
  20781.                           scroll = 0;
  20782.                           rebuild_dynamic_array = TRUE;
  20783.                          }
  20784.      else
  20785.      if (is_scroll_word)  scroll = -zscrolln/rowincr;
  20786.      else                 scroll = -zscrolln;
  20787.    }
  20788.    else scroll = 0;
  20789.  
  20790.    if (scroll != 0) rebuild_dynamic_array = TRUE;
  20791.  
  20792.  } while (prc == 0);
  20793.  
  20794.  return TRUE;
  20795.  
  20796. }
  20797.  
  20798. /****** View articles. ***********************************************/
  20799.  
  20800. Bool
  20801. NNMvar(np,gp)
  20802. Rstruc nncb           *np;
  20803. Rstruc newsgroup      *gp;
  20804. {
  20805.  struct ntdynarray    *dynarray;
  20806.  char                 *nntdyna;
  20807.  int                   depth;
  20808.  int                   dynsize;
  20809.  
  20810.  /* Get depth of dynamic area (number of rows to display on screen) */
  20811.  
  20812.  (void)NNMispf(np,
  20813.        "PQUERY PANEL(NNMDAR) AREANAME(NNTDYNA) DEPTH(NNTDEPTH)");
  20814.  if (np->ispfrc != 0) return FALSE;
  20815.  depth = NNMiget(np,"NNTDEPTH ");
  20816.  
  20817.  /* Allocate a block of "ntdynarray" article pointers, one element
  20818.   * for each article currently being displayed.  This must be big
  20819.   * enough to fill up the screen.  It is rebuilt every time the
  20820.   * display changes, through scrolling or selection activity.
  20821.   */
  20822.  
  20823.  GETMAIN(dynarray, struct ntdynarray, depth,
  20824.          "newsarticle dynamic array");
  20825.  if (!dynarray) return FALSE;
  20826.  
  20827.  /* Get storage for ISPF dynamic area variable to be constructed. */
  20828.  
  20829.  dynsize = 80*depth;
  20830.  GETMAIN(nntdyna, char, dynsize+1, "NNTDYNA buffer");
  20831.  if (!nntdyna) return FALSE;
  20832.  
  20833.  np->top_article               = 0;
  20834.  np->top_sorted_article        = NULL;
  20835.  np->repeat_find               = FALSE;
  20836.  np->article_criterion_changed = TRUE;
  20837.  *np->selsubj                  = '\0';
  20838.  
  20839.  if (!view_articles(np,gp,dynarray,nntdyna,depth,dynsize)) return FALSE;
  20840.  
  20841.  FREEMAIN(nntdyna,"NNTDYNA buffer");
  20842.  FREEMAIN(dynarray,"newsarticle dynamic area");
  20843.  
  20844.  return TRUE;
  20845.  
  20846. }
  20847. ./   ADD NAME=NNMVIEW,SSI=01460008
  20848.  
  20849.  /********************************************************************/
  20850.  /*                                                                  */
  20851.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993    */
  20852.  /*                                                                  */
  20853.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  20854.  /*                                                                  */
  20855.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  20856.  /* including the implied warranties of merchantability and fitness, */
  20857.  /* are expressly denied.                                            */
  20858.  /*                                                                  */
  20859.  /* Provided this copyright notice is included, this software may    */
  20860.  /* be freely distributed and not offered for sale.                  */
  20861.  /*                                                                  */
  20862.  /* Changes or modifications may be made and used only by the maker  */
  20863.  /* of same, and not further distributed.  Such modifications should */
  20864.  /* be mailed to the author for consideration for addition to the    */
  20865.  /* software and incorporation in subsequent releases.               */
  20866.  /*                                                                  */
  20867.  /********************************************************************/
  20868.  
  20869. #pragma  csect(code,  "NN@VIEW ")
  20870. #pragma  csect(static,"NN$VIEW ")
  20871. #include "nn.h"
  20872.  
  20873. struct browser {
  20874.    struct newsgroup     *gp;
  20875.    struct newsarticle   *ap;
  20876.    struct texthdr       *thp;            /* text header pointer      */
  20877.    struct textline     **tv;             /* text vector              */
  20878.                char     *bda;            /* dynamic area address     */
  20879.                char     *work;           /* find work area address   */
  20880.                char     *firstpos;       /* beginning of actual data */
  20881.                char     *lastpos;        /* end of actual data       */
  20882.                int       depth;          /* dynamic area depth       */
  20883.                int       lvl;            /* last visible line        */
  20884.                int       size;           /* dynamic area size        */
  20885.                int       more_rows;      /* Scroll request row count */
  20886.                int       rowfactor;      /* # physical rows per line */
  20887.                int       screenbump;     /* # physical rows * width  */
  20888.                int       top;            /* top row number           */
  20889.                int       total;          /* total number of rows     */
  20890.                int       coloff;         /* offset from LEFT/RIGHT   */
  20891.                int       cols;           /* 1 if COLS done, else 0   */
  20892.                int       maxlen;         /* maximum text length      */
  20893.                int       maxcoloff;      /* maximum right scroll     */
  20894.                Bool      override_scroll;/* set by some commands     */
  20895.                Bool      highlighted;    /* set if FIND highlights   */
  20896.                Bool      reinit_browse;  /* set if text changed      */
  20897.                Bool      exit_browse;    /* set if browse must exit  */
  20898.                Bool      find_hit_end;   /* top/bottom of data reach */
  20899.                int       find_count;     /* used by FIND ALL         */
  20900.                int       find_row;       /* row where last found     */
  20901.                int       find_col;       /* col where last found     */
  20902.                int       found_row;      /* row where last found     */
  20903.                int       found_col;      /* col where last found     */
  20904.                int       csrpos;         /* cursor position          */
  20905.                int       find_csrpos;    /* col where last found     */
  20906.                int       found_left;     /* pos left of found string */
  20907.                int       found_right;    /* pos right of found string*/
  20908.                char      cursor     [9]; /* cursor field name        */
  20909.                char      find_cursor[9]; /* row where last found     */
  20910.                char      title     [81]; /* title                    */
  20911.                char      cols_line [81]; /* cols line                */
  20912.                char      zcmd      [81]; /* command input            */
  20913.               };
  20914.  
  20915. /******* torot13 ******************************************************/
  20916.  
  20917. static char
  20918. torot13(c)
  20919. char    c;
  20920. {
  20921.  char   d;
  20922.  if (!isalpha(c)) d = c;
  20923.  else switch (c) {
  20924.    case 'a':   d = 'n'; break;
  20925.    case 'b':   d = 'o'; break;
  20926.    case 'c':   d = 'p'; break;
  20927.    case 'd':   d = 'q'; break;
  20928.    case 'e':   d = 'r'; break;
  20929.    case 'f':   d = 's'; break;
  20930.    case 'g':   d = 't'; break;
  20931.    case 'h':   d = 'u'; break;
  20932.    case 'i':   d = 'v'; break;
  20933.    case 'j':   d = 'w'; break;
  20934.    case 'k':   d = 'x'; break;
  20935.    case 'l':   d = 'y'; break;
  20936.    case 'm':   d = 'z'; break;
  20937.    case 'n':   d = 'a'; break;
  20938.    case 'o':   d = 'b'; break;
  20939.    case 'p':   d = 'c'; break;
  20940.    case 'q':   d = 'd'; break;
  20941.    case 'r':   d = 'e'; break;
  20942.    case 's':   d = 'f'; break;
  20943.    case 't':   d = 'g'; break;
  20944.    case 'u':   d = 'h'; break;
  20945.    case 'v':   d = 'i'; break;
  20946.    case 'w':   d = 'j'; break;
  20947.    case 'x':   d = 'k'; break;
  20948.    case 'y':   d = 'l'; break;
  20949.    case 'z':   d = 'm'; break;
  20950.    case 'A':   d = 'N'; break;
  20951.    case 'B':   d = 'O'; break;
  20952.    case 'C':   d = 'P'; break;
  20953.    case 'D':   d = 'Q'; break;
  20954.    case 'E':   d = 'R'; break;
  20955.    case 'F':   d = 'S'; break;
  20956.    case 'G':   d = 'T'; break;
  20957.    case 'H':   d = 'U'; break;
  20958.    case 'I':   d = 'V'; break;
  20959.    case 'J':   d = 'W'; break;
  20960.    case 'K':   d = 'X'; break;
  20961.    case 'L':   d = 'Y'; break;
  20962.    case 'M':   d = 'Z'; break;
  20963.    case 'N':   d = 'A'; break;
  20964.    case 'O':   d = 'B'; break;
  20965.    case 'P':   d = 'C'; break;
  20966.    case 'Q':   d = 'D'; break;
  20967.    case 'R':   d = 'E'; break;
  20968.    case 'S':   d = 'F'; break;
  20969.    case 'T':   d = 'G'; break;
  20970.    case 'U':   d = 'H'; break;
  20971.    case 'V':   d = 'I'; break;
  20972.    case 'W':   d = 'J'; break;
  20973.    case 'X':   d = 'K'; break;
  20974.    case 'Y':   d = 'L'; break;
  20975.    case 'Z':   d = 'M'; break;
  20976.  }
  20977.  
  20978.  return d;
  20979. }
  20980.  
  20981. /******* EXTRACT command **********************************************/
  20982.  
  20983. static Bool
  20984. process_extract_command(np,bp,operands)
  20985. Rstruc nncb         *np;
  20986. Rstruc browser      *bp;
  20987. char                *operands;
  20988. {
  20989.  Rstruc newsarticle *ap = bp->ap;
  20990.  
  20991.  if (!ap) (void)NNMivput(np,"NNTNUM ","",-1);
  20992.  np->extract_file = NULL;
  20993.  np->printing     = FALSE;
  20994.  (void)NNMispf(np,"CONTROL DISPLAY SAVE");
  20995.  (void)NNMxtx(np,ap,TRUE);                   /* Extract text */
  20996.  (void)NNMispf(np,"CONTROL DISPLAY RESTORE");
  20997.  
  20998.  return TRUE;
  20999. }
  21000.  
  21001. /******* PRINT command ************************************************/
  21002.  
  21003. static Bool
  21004. process_print_command(np,bp,operands)
  21005. Rstruc nncb         *np;
  21006. Rstruc browser      *bp;
  21007. char                *operands;
  21008. {
  21009.  Rstruc newsarticle *ap = bp->ap;
  21010.  
  21011.  if (!ap) (void)NNMivput(np,"NNTNUM ","",-1);
  21012.  np->extract_file = NULL;
  21013.  np->printing     = TRUE;
  21014.  (void)NNMispf(np,"CONTROL DISPLAY SAVE");
  21015.  (void)NNMxtx(np,ap,TRUE);                   /* Print text */
  21016.  (void)NNMispf(np,"CONTROL DISPLAY RESTORE");
  21017.  
  21018.  return TRUE;
  21019. }
  21020.  
  21021. /******* UNREAD command ***********************************************/
  21022.  
  21023. static Bool
  21024. process_unread_command(np,bp,operands)
  21025. Rstruc nncb         *np;
  21026. Rstruc browser      *bp;
  21027. char                *operands;
  21028. {
  21029.  
  21030.  np->another_article = UNREAD_THIS_ARTICLE;
  21031.  bp->exit_browse = TRUE;
  21032.  
  21033.  return TRUE;
  21034. }
  21035.  
  21036. /******* ROT13 command ************************************************/
  21037.  
  21038. static Bool
  21039. process_rot13_command(np,bp,operands)
  21040. Rstruc nncb         *np;
  21041. Rstruc browser      *bp;
  21042. char                *operands;
  21043. {
  21044.  struct textline    *tp;
  21045.  char               *cp;
  21046.  char               *cpe;
  21047.  
  21048.  for (tp=bp->thp->first_text_line; tp; tp=tp->next) {
  21049.    for (cp=tp->tab_expanded_text, cpe=cp+tp->tab_expanded_text_length;
  21050.         cp < cpe;
  21051.         cp++) {
  21052.      *cp = torot13(*cp);
  21053.    }
  21054.  }
  21055.  
  21056.  bp->reinit_browse = TRUE;
  21057.  
  21058.  return TRUE;
  21059. }
  21060.  
  21061. /******* REPLY command ************************************************/
  21062.  
  21063. static Bool
  21064. process_reply_command(np,bp,operands)
  21065. Rstruc nncb         *np;
  21066. Rstruc browser      *bp;
  21067. char                *operands;
  21068. {
  21069.  
  21070.  (void)NNMispf(np,"CONTROL DISPLAY SAVE");
  21071.  NNMdmail(np,bp->gp,bp->ap);       /* Send mail message */
  21072.  (void)NNMispf(np,"CONTROL DISPLAY RESTORE");
  21073.  return TRUE;
  21074. }
  21075.  
  21076. /******* FOLLOWUP command *********************************************/
  21077.  
  21078. static Bool
  21079. process_followup_command(np,bp,operands)
  21080. Rstruc nncb         *np;
  21081. Rstruc browser      *bp;
  21082. char                *operands;
  21083. {
  21084.  
  21085.  (void)NNMispf(np,"CONTROL DISPLAY SAVE");
  21086.  NNMdpost(np,bp->gp,bp->ap);       /* Post followup */
  21087.  (void)NNMispf(np,"CONTROL DISPLAY RESTORE");
  21088.  return TRUE;
  21089. }
  21090.  
  21091. /******* NEXT command *************************************************/
  21092.  
  21093. static Bool
  21094. process_next_command(np,bp,operands)
  21095. Rstruc nncb         *np;
  21096. Rstruc browser      *bp;
  21097. char                *operands;
  21098. {
  21099.  
  21100.  np->another_article = NEXT_ARTICLE;
  21101.  bp->exit_browse = TRUE;
  21102.  return TRUE;
  21103. }
  21104.  
  21105. /******* PREV command *************************************************/
  21106.  
  21107. static Bool
  21108. process_prev_command(np,bp,operands)
  21109. Rstruc nncb         *np;
  21110. Rstruc browser      *bp;
  21111. char                *operands;
  21112. {
  21113.  
  21114.  np->another_article = PREV_ARTICLE;
  21115.  bp->exit_browse = TRUE;
  21116.  return TRUE;
  21117. }
  21118.  
  21119. /******* NEXTU command ************************************************/
  21120.  
  21121. static Bool
  21122. process_nextu_command(np,bp,operands)
  21123. Rstruc nncb         *np;
  21124. Rstruc browser      *bp;
  21125. char                *operands;
  21126. {
  21127.  
  21128.  np->another_article = NEXT_UNREAD_ARTICLE;
  21129.  bp->exit_browse = TRUE;
  21130.  return TRUE;
  21131. }
  21132.  
  21133. /******* PREVU command ************************************************/
  21134.  
  21135. static Bool
  21136. process_prevu_command(np,bp,operands)
  21137. Rstruc nncb         *np;
  21138. Rstruc browser      *bp;
  21139. char                *operands;
  21140. {
  21141.  
  21142.  np->another_article = PREV_UNREAD_ARTICLE;
  21143.  bp->exit_browse = TRUE;
  21144.  return TRUE;
  21145. }
  21146.  
  21147. /******* NEXTT command ************************************************/
  21148.  
  21149. static Bool
  21150. process_nextt_command(np,bp,operands)
  21151. Rstruc nncb         *np;
  21152. Rstruc browser      *bp;
  21153. char                *operands;
  21154. {
  21155.  
  21156.  np->another_article = NEXT_TABLED_ARTICLE;
  21157.  bp->exit_browse = TRUE;
  21158.  return TRUE;
  21159. }
  21160.  
  21161. /******* PREVT command ************************************************/
  21162.  
  21163. static Bool
  21164. process_prevt_command(np,bp,operands)
  21165. Rstruc nncb         *np;
  21166. Rstruc browser      *bp;
  21167. char                *operands;
  21168. {
  21169.  
  21170.  np->another_article = PREV_TABLED_ARTICLE;
  21171.  bp->exit_browse = TRUE;
  21172.  return TRUE;
  21173. }
  21174.  
  21175. /******* NEXTSUBJ command *********************************************/
  21176.  
  21177. static Bool
  21178. process_nextsubj_command(np,bp,operands)
  21179. Rstruc nncb         *np;
  21180. Rstruc browser      *bp;
  21181. char                *operands;
  21182. {
  21183.  
  21184.  np->another_article = NEXT_THREAD_ARTICLE;
  21185.  bp->exit_browse = TRUE;
  21186.  return TRUE;
  21187. }
  21188.  
  21189. /******* PREVSUBJ command *********************************************/
  21190.  
  21191. static Bool
  21192. process_prevsubj_command(np,bp,operands)
  21193. Rstruc nncb         *np;
  21194. Rstruc browser      *bp;
  21195. char                *operands;
  21196. {
  21197.  
  21198.  np->another_article = PREV_THREAD_ARTICLE;
  21199.  bp->exit_browse = TRUE;
  21200.  return TRUE;
  21201. }
  21202.  
  21203. /******* FIRSTSUBJ command ********************************************/
  21204.  
  21205. static Bool
  21206. process_firstsubj_command(np,bp,operands)
  21207. Rstruc nncb         *np;
  21208. Rstruc browser      *bp;
  21209. char                *operands;
  21210. {
  21211.  
  21212.  np->another_article = FIRST_THREAD_ARTICLE;
  21213.  bp->exit_browse = TRUE;
  21214.  return TRUE;
  21215. }
  21216.  
  21217. /******* LASTSUBJ command *********************************************/
  21218.  
  21219. static Bool
  21220. process_lastsubj_command(np,bp,operands)
  21221. Rstruc nncb         *np;
  21222. Rstruc browser      *bp;
  21223. char                *operands;
  21224. {
  21225.  
  21226.  np->another_article = LAST_THREAD_ARTICLE;
  21227.  bp->exit_browse = TRUE;
  21228.  return TRUE;
  21229. }
  21230.  
  21231. /******* NEWSUBJ command **********************************************/
  21232.  
  21233. static Bool
  21234. process_newsubj_command(np,bp,operands)
  21235. Rstruc nncb         *np;
  21236. Rstruc browser      *bp;
  21237. char                *operands;
  21238. {
  21239.  
  21240.  np->another_article = NEW_THREAD_ARTICLE;
  21241.  bp->exit_browse = TRUE;
  21242.  return TRUE;
  21243. }
  21244.  
  21245. /******* SUBJECT command **********************************************/
  21246.  
  21247. static Bool
  21248. process_subject_command(np,bp,operands)
  21249. Rstruc nncb         *np;
  21250. Rstruc browser      *bp;
  21251. char                *operands;
  21252. {
  21253.  
  21254.  /* If anything remaining on the command line, make it the new    */
  21255.  /* subject, otherwise just display the current subject.          */
  21256.  
  21257.  if (*operands) {
  21258.    memset(np->selsubj,0,sizeof(np->selsubj));
  21259.    strncpy(np->selsubj,operands,sizeof(np->selsubj)-1);
  21260.  WARN1(
  21261.   "Subject changed.  All subject searches will use the new subject.");
  21262.  }
  21263.  else if (!*np->selsubj) {
  21264.    WARN1(
  21265.     "No current subject has been set by a subject-related command.");
  21266.  }
  21267.  else {
  21268.    WARN2("Current subject: %s", np->selsubj);
  21269.  }
  21270.  return TRUE;
  21271. }
  21272.  
  21273. /******* OPTIONS command **********************************************/
  21274.  
  21275. static Bool
  21276. process_options_command(np,bp,operands)
  21277. Rstruc nncb         *np;
  21278. Rstruc browser      *bp;
  21279. char                *operands;
  21280. {
  21281.  
  21282.  NNMdsopt(np,operands);         /* Do "set options" function */
  21283.  np->another_article = REDISPLAY_ARTICLE;
  21284.  bp->exit_browse = TRUE;
  21285.  return TRUE;
  21286. }
  21287.  
  21288. /******* HEADERS command **********************************************/
  21289.  
  21290. static Bool
  21291. process_headers_command(np,bp,operands)
  21292. Rstruc nncb         *np;
  21293. Rstruc browser      *bp;
  21294. char                *operands;
  21295. {
  21296.  
  21297.  NNMdsopt(np,"1");              /* Do "set options 1" function */
  21298.  np->another_article = REDISPLAY_ARTICLE;
  21299.  bp->exit_browse = TRUE;
  21300.  return TRUE;
  21301. }
  21302.  
  21303.  
  21304. /******* COLS command *************************************************/
  21305.  
  21306. static Bool
  21307. process_cols_command(np,bp,operands)
  21308. Rstruc nncb         *np;
  21309. Rstruc browser      *bp;
  21310. char                *operands;
  21311. {
  21312.  
  21313.  bp->cols = 1;
  21314.  *bp->cols_line = '\0';
  21315.  bp->reinit_browse = TRUE;
  21316.  return TRUE;
  21317. }
  21318.  
  21319. /******* RESET command ************************************************/
  21320.  
  21321. static Bool
  21322. process_reset_command(np,bp,operands)
  21323. Rstruc nncb         *np;
  21324. Rstruc browser      *bp;
  21325. char                *operands;
  21326. {
  21327.  
  21328.  bp->cols = 0;
  21329.  *bp->cols_line = '\0';
  21330.  bp->reinit_browse = TRUE;
  21331.  return TRUE;
  21332. }
  21333.  
  21334. /******* DISPLAY command **********************************************/
  21335.  
  21336. static Bool
  21337. process_display_command(np,bp,operands)
  21338. Rstruc nncb         *np;
  21339. Rstruc browser      *bp;
  21340. char                *operands;
  21341. {
  21342.  unsigned int        u;
  21343.  
  21344.  switch (strlen(operands)) {
  21345.    case 1: np->text_dispchar = operands[0];
  21346.            break;
  21347.    case 2: if (1 != sscanf(operands,"%x",&u)) {
  21348.              ERR1("Invalid hex character representation.");
  21349.              return FALSE;
  21350.            }
  21351.            np->text_dispchar = u;
  21352.            break;
  21353.    default:
  21354.            ERR1("A single character must be specified.");
  21355.            return FALSE;
  21356.  }
  21357.  bp->reinit_browse = TRUE;
  21358.  return TRUE;
  21359. }
  21360.  
  21361. /******* LOCATE command ***********************************************/
  21362.  
  21363. static Bool
  21364. process_locate_command(np,bp,operands)
  21365. Rstruc nncb         *np;
  21366. Rstruc browser      *bp;
  21367. char                *operands;
  21368. {
  21369.  int                 locnum;
  21370.  char                junk[72];
  21371.  
  21372.  if (1 != sscanf(operands, "%d %s", &locnum, junk)) {
  21373.    ERR1("The LOCATE command requires a line number.");
  21374.    return FALSE;
  21375.  }
  21376.  
  21377.  bp->top = locnum;
  21378.  bp->more_rows = 0;
  21379.  bp->override_scroll = TRUE;
  21380.  bp->reinit_browse = TRUE;
  21381.  return TRUE;
  21382. }
  21383.  
  21384. /***** Helper functions for FIND **************************************/
  21385.  
  21386. /*--------------------------------------------------------------------*
  21387.  * Get quoted FIND string.                                            *
  21388.  *--------------------------------------------------------------------*/
  21389.  
  21390. static char *
  21391. get_quoted_find_string(np,cp,qform)
  21392. Rstruc nncb         *np;
  21393. char                *cp;
  21394. char                *qform;
  21395. {
  21396.  char                quote     = *cp;
  21397.  char                termchar  = '\0';
  21398.  
  21399.  for (cp++;;cp++) {
  21400.    if (*cp == quote) {
  21401.      switch (*(cp+1)) {
  21402.        case '\0':
  21403.        case ' ':  termchar = '\0'; break;
  21404.        case 'c':
  21405.        case 'C':  termchar = 'C' ; break;
  21406.        case 't':
  21407.        case 'T':  termchar = 'T' ; break;
  21408.        case 'x':
  21409.        case 'X':  termchar = 'X' ; break;
  21410.        case 'p':
  21411.        case 'P':  termchar = 'P' ; break;
  21412.        default:   continue;
  21413.      }
  21414.      if (termchar) {
  21415.        switch (*(cp+2)) {
  21416.          case '\0':
  21417.          case ' ':  break;
  21418.          default:   continue;
  21419.        } 
  21420.        if (*qform != FIND_QUOTED) {
  21421.          ERR1(
  21422.       "Invalid string; Do not surround a quoted string with letters.");
  21423.          *qform = FIND_BADFORM;
  21424.          return NULL;
  21425.        } 
  21426.        else {
  21427.          switch (termchar) {
  21428.            case 'C': *qform = FIND_C; break;
  21429.            case 'T': *qform = FIND_T; break;
  21430.            case 'X': *qform = FIND_X; break;
  21431.            case 'P': *qform = FIND_P; break;
  21432.          }
  21433.          *cp = '\0'; /* kill the quote because it's the character */
  21434.          cp++;       /* that the caller will kill, not the quote  */
  21435.        } 
  21436.      }
  21437.      break;
  21438.    }
  21439.    else if (!*cp) {
  21440.      ERR1(
  21441.      "Missing quote; The FIND command requires balanced quote marks.");
  21442.      *qform = FIND_BADFORM;
  21443.      return NULL;
  21444.    }
  21445.  }
  21446.  return cp;
  21447. }
  21448.  
  21449. /*--------------------------------------------------------------------*
  21450.  * Get FIND operand.                                                  *
  21451.  *--------------------------------------------------------------------*/
  21452.  
  21453. static char *
  21454. get_find_operand(np,opp,qform)
  21455. Rstruc nncb     *np;
  21456. char           **opp;
  21457. char            *qform;
  21458. {
  21459.  char           *cp    = *opp;
  21460.  char           *start = NULL;
  21461.  
  21462.  cp = skip_ISPF_whitespace(cp);
  21463.  
  21464.  if (!*cp) return NULL;
  21465.  if (*cp == '\'' || *cp == '"') {
  21466.    start = cp+1;
  21467.    *qform = FIND_QUOTED;
  21468.    if (!(cp = get_quoted_find_string(np,cp,qform))) return NULL;
  21469.  }
  21470.  else if ((*(cp+1) == '\'' || *(cp+1) == '"')) {
  21471.    switch (*cp) {
  21472.      case 'c':
  21473.      case 'C': *qform = FIND_C; break;
  21474.      case 't':
  21475.      case 'T': *qform = FIND_T; break;
  21476.      case 'x':
  21477.      case 'X': *qform = FIND_X; break;
  21478.      case 'p':
  21479.      case 'P': *qform = FIND_P; break;
  21480.      default:  *qform = FIND_UNQUOTED; break;
  21481.    }
  21482.    if (*qform != FIND_UNQUOTED) {
  21483.      cp++;
  21484.      start = cp+1;
  21485.      if (!(cp = get_quoted_find_string(np,cp,qform))) return NULL;
  21486.    }
  21487.    else {
  21488.      start = cp;
  21489.      find_ISPF_whitespace(cp,start);
  21490.    }
  21491.  }
  21492.  else {
  21493.    start = cp;
  21494.    *qform = FIND_UNQUOTED;
  21495.    find_ISPF_whitespace(cp,start);
  21496.  }
  21497.  if (*cp) {
  21498.    *cp  = '\0';
  21499.    *opp = cp+1;
  21500.  }
  21501.  else {
  21502.    *opp = cp;
  21503.  }
  21504.  return start;
  21505. }
  21506.  
  21507. /*--------------------------------------------------------------------*
  21508.  * Find it.                                                           *
  21509.  *--------------------------------------------------------------------*/
  21510.  
  21511. #define REND                 (r+(*tpp)->tab_expanded_text_length)
  21512. #define PRECEDED_BY_VERBIAGE (q>r && isalnum(*(q-1)))
  21513. #define FOLLOWED_BY_VERBIAGE (q+findlen<REND && isalnum(*(q+findlen)))
  21514.  
  21515. static Bool
  21516. find_it(np,bp,find_string,findlen,
  21517.                           find_type,find_what,find_trans,
  21518.                           find_left_bound,find_right_bound)
  21519. Rstruc nncb       *np;
  21520. Rstruc browser    *bp;
  21521. char              *find_string;
  21522. int                findlen;
  21523. char               find_type;      /* chars word prefix suffix */
  21524. char               find_what;      /* next prev first last all */
  21525. char               find_trans;     /* caps asis generic        */
  21526. int                find_left_bound;
  21527. int                find_right_bound;
  21528. {
  21529.  struct textline **tpp;
  21530.  char             *p;
  21531.  char             *q;
  21532.  char             *r;
  21533.  int               row;
  21534.  int               col;
  21535.  int               complen;
  21536.  int               lcol;
  21537.  int               rcol;
  21538.  int               ecol;
  21539.  Bool              backward_find;
  21540.  
  21541.  lcol = find_left_bound - 1;
  21542.  rcol = find_right_bound - 1;
  21543.  row  = bp->find_row;
  21544.  col  = bp->find_col;
  21545.  
  21546.  switch (find_what) {
  21547.    case FIND_NEXT:
  21548.                     if (bp->find_hit_end) {
  21549.                       bp->find_hit_end = FALSE;
  21550.                       row = 0;
  21551.                       col = lcol;
  21552.                     }
  21553.                     else if (EQUAL(bp->find_cursor,"NNBDYNA")) {
  21554.                       row = bp->top+((bp->find_csrpos-1)/80)-bp->cols-1;
  21555.                       col = (bp->find_csrpos-1) % 80 + bp->coloff;
  21556.                       if (++col >= bp->maxlen) {
  21557.                         row++;
  21558.                         col = lcol;
  21559.                       }
  21560.                     }
  21561.                     else {
  21562.                       row = bp->top - 1;
  21563.                       if (row < 0) row = 0;
  21564.                       col = lcol;
  21565.                     }
  21566.                     backward_find = FALSE;
  21567.                     break;
  21568.    case FIND_PREV:
  21569.                     if (bp->find_hit_end) {
  21570.                       bp->find_hit_end = FALSE;
  21571.                       row = bp->total - 1;
  21572.                       col = rcol;
  21573.                     }
  21574.                     else if (EQUAL(bp->find_cursor,"NNBDYNA")) {
  21575.                       row = bp->top+((bp->find_csrpos-1)/80)-bp->cols-1;
  21576.                       col = (bp->find_csrpos-1) % 80 + bp->coloff;
  21577.                       if (--col < 0) {
  21578.                         row--;
  21579.                         col = rcol;
  21580.                       }
  21581.                     }
  21582.                     else {
  21583.                       row = bp->total - 1;
  21584.                       col = rcol;
  21585.                     }
  21586.                     backward_find = TRUE;
  21587.                     break;
  21588.    case FIND_FIRST:
  21589.                     if (bp->find_hit_end) {
  21590.                       bp->find_hit_end = FALSE;
  21591.                     }
  21592.                     row = 0;
  21593.                     col = lcol;
  21594.                     backward_find = FALSE;
  21595.                     break;
  21596.    case FIND_LAST:
  21597.                     if (bp->find_hit_end) {
  21598.                       bp->find_hit_end = FALSE;
  21599.                     }
  21600.                     row = bp->total - 1;
  21601.                     col = rcol;
  21602.                     backward_find = TRUE;
  21603.                     break;
  21604.    case FIND_ALL:
  21605.                     col++;
  21606.                     backward_find = FALSE;
  21607.                     break;
  21608.  }
  21609.  
  21610.  if (backward_find == FALSE) {
  21611.    /* forward find */
  21612.    if (col < lcol) col = lcol;
  21613.    else if (col > rcol) {
  21614.      col = lcol;
  21615.      row++;
  21616.    }
  21617.    for (tpp = &bp->tv[row]; row < bp->total; tpp++, col=lcol, row++) {
  21618.      ecol = (*tpp)->tab_expanded_text_length - 1;
  21619.      if (ecol > rcol) ecol = rcol;
  21620.      if (col > ecol) continue;
  21621.      p = (*tpp)->tab_expanded_text;
  21622.      if (find_trans == FIND_CAPS) {
  21623.        copy_uppercase(bp->work,p);
  21624.        r = bp->work;
  21625.      }
  21626.      else r = p;
  21627.      complen = ecol-col+1;
  21628.      for (q = r + col;;q++) {
  21629.        q = memchr(q,find_string[0],complen);
  21630.        if (!q) break;
  21631.        col = q - r;
  21632.        complen = ecol-col+1;
  21633.        if (complen < findlen) break;
  21634.        if (!memcmp(q,find_string,findlen)) {
  21635.          switch (find_type) {
  21636.            case FIND_CHARS:  break;
  21637.            case FIND_WORD:
  21638.                 if (PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
  21639.                     continue;
  21640.                 break;
  21641.            case FIND_PREFIX:
  21642.                 if (PRECEDED_BY_VERBIAGE || !FOLLOWED_BY_VERBIAGE)
  21643.                     continue;
  21644.                 break;
  21645.            case FIND_SUFFIX:
  21646.                 if (!PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
  21647.                    continue;
  21648.                 break;
  21649.          }
  21650.          bp->find_row = row;
  21651.          bp->find_col = col;
  21652.          return TRUE;
  21653.        } 
  21654.      }
  21655.    }
  21656.    bp->find_row = 0;
  21657.    bp->find_col = 0;
  21658.    bp->find_hit_end = TRUE;
  21659.    return FALSE;
  21660.  }
  21661.  else {
  21662.    /* backward find */
  21663.    if (row >= bp->total) row = bp->total - 1;
  21664.    if (col > rcol-findlen+1) col = rcol-findlen+1;
  21665.    else if (col < lcol) {
  21666.      col = rcol-findlen+1;
  21667.      row--;
  21668.    }
  21669.    for (tpp=&bp->tv[row]; row >= 0; tpp--, col=rcol-findlen+1, row--) {
  21670.      ecol = (*tpp)->tab_expanded_text_length - 1;
  21671.      if (ecol > rcol) ecol = rcol;
  21672.      if (col > ecol) col = ecol;
  21673.      p = (*tpp)->tab_expanded_text;
  21674.      if (find_trans == FIND_CAPS) {
  21675.        copy_uppercase(bp->work,p);
  21676.        r = bp->work;
  21677.      }
  21678.      else r = p;
  21679.      for (q = r + col; q >= r; q--) {
  21680.        if (!memcmp(q,find_string,findlen)) {
  21681.          switch (find_type) {
  21682.            case FIND_CHARS:  break;
  21683.            case FIND_WORD:
  21684.                 if (PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
  21685.                     continue;
  21686.                 break;
  21687.            case FIND_PREFIX:
  21688.                 if (PRECEDED_BY_VERBIAGE || !FOLLOWED_BY_VERBIAGE)
  21689.                     continue;
  21690.                 break;
  21691.            case FIND_SUFFIX:
  21692.                 if (!PRECEDED_BY_VERBIAGE || FOLLOWED_BY_VERBIAGE)
  21693.                    continue;
  21694.                 break;
  21695.          }
  21696.          col = q - r;
  21697.          bp->find_row = row;
  21698.          bp->find_col = col;
  21699.          return TRUE;
  21700.        } 
  21701.      }
  21702.    }
  21703.    bp->find_row = bp->total - 1;
  21704.    bp->find_col = bp->maxlen;
  21705.    bp->find_hit_end = TRUE;
  21706.    return FALSE;
  21707.  }
  21708.  
  21709. }
  21710.  
  21711. /********* FIND command ***********************************************/
  21712.  
  21713. static Bool
  21714. process_find_command(np,bp,operands)
  21715. Rstruc nncb         *np;
  21716. Rstruc browser      *bp;
  21717. char                *operands;
  21718. {
  21719.  char        *find_operand [64];
  21720.  char        *show_type;
  21721.  char        *cp;
  21722.  char        *opcopy;
  21723.  char        *op;
  21724.  char        *p;
  21725.  char        *q;
  21726.  char         find_qform   [64];
  21727.  Bool         finderror = FALSE;
  21728.  Bool         out_of_bounds = FALSE;
  21729.  int          find_operand_count;
  21730.  int          ox;
  21731.  int          find_left_bound;
  21732.  int          find_right_bound;
  21733.  int          n;
  21734.  int          len;
  21735.  int          findlen;
  21736.  char         find_what;      /* next prev first last all */
  21737.  char         find_type;      /* chars word prefix suffix */
  21738.  char         find_trans;     /* caps asis generic        */
  21739.  char         find_form;      /* unquoted quoted c x t p  */
  21740.  char         ff;             /* unquoted quoted c x t p  */
  21741.  Bool         hit_end                = FALSE;
  21742.  Bool         find_string_given      = FALSE;
  21743.  Bool         find_what_given        = FALSE;
  21744.  Bool         find_type_given        = FALSE;
  21745.  Bool         find_left_bound_given  = FALSE;
  21746.  Bool         find_right_bound_given = FALSE;
  21747.  char         operand_copy [81];
  21748.  char         find_string  [81];
  21749.  char         temp         [81];
  21750.  char         show_string [129];
  21751.  char         shortmsg    [129];
  21752.  char         longmsg     [129];
  21753.  
  21754.  strcpy(operand_copy,operands);
  21755.  
  21756.  find_operand_count = 0;
  21757.  for (ox = 0, opcopy = operand_copy; ox < 64; ox++) {
  21758.    ff = FIND_UNQUOTED;
  21759.    op = get_find_operand(np,&opcopy,&ff);
  21760.    if (ff == FIND_BADFORM) return FALSE;
  21761.    if (!op) break;
  21762.    find_operand[ox] = op;
  21763.    find_qform[ox] = ff;
  21764.    find_operand_count++;
  21765.  }
  21766.  
  21767.  if (find_operand_count == 0) {
  21768.    if (!*np->text_find_string) {
  21769.      ERR1("The first FIND command requires an operand.");
  21770.      return FALSE;
  21771.    }
  21772.    strcpy(find_string,np->text_find_string);
  21773.    find_what        = np->text_find_what;
  21774.    find_type        = np->text_find_type;
  21775.    find_trans       = np->text_find_trans;
  21776.    find_left_bound  = np->text_find_left_bound;
  21777.    find_right_bound = np->text_find_right_bound;
  21778.  }
  21779.  else {
  21780.    find_what        = FIND_NEXT;
  21781.    find_type        = FIND_CHARS;
  21782.    find_trans       = FIND_CAPS;
  21783.    find_left_bound  = 1;
  21784.    find_right_bound = bp->maxlen;
  21785.    for (ox = 0; ox < find_operand_count; ox++) {
  21786.      op = find_operand[ox];
  21787.      ff = find_qform[ox];
  21788.      if (ff != FIND_UNQUOTED) {
  21789.        if (find_string_given) finderror = TRUE;
  21790.        else {
  21791.          strcpy(find_string,op);
  21792.          find_form = ff;
  21793.          find_string_given = TRUE;
  21794.        } 
  21795.      }
  21796.      else {
  21797.        copy_uppercase(temp,op);
  21798.        if (EQUAL(temp,"*")) {
  21799.          if (find_string_given) finderror = TRUE;
  21800.          else {
  21801.            strcpy(find_string,np->text_find_string);
  21802.            find_form = ff;
  21803.            find_string_given = TRUE;
  21804.          }
  21805.        } 
  21806.        else if (find_operand_count == 1) {
  21807.          strcpy(find_string,op);
  21808.          find_form = ff;
  21809.          find_string_given = TRUE;
  21810.        } 
  21811.        else if (EQUAL(temp,"NEXT")) {
  21812.          if (find_what_given) finderror = TRUE;
  21813.          else {
  21814.            find_what = FIND_NEXT;
  21815.            find_what_given = TRUE;
  21816.          }
  21817.        } 
  21818.        else if (EQUAL(temp,"PREV")) {
  21819.          if (find_what_given) finderror = TRUE;
  21820.          else {
  21821.            find_what = FIND_PREV;
  21822.            find_what_given = TRUE;
  21823.          }
  21824.        } 
  21825.        else if (EQUAL(temp,"FIRST")) {
  21826.          if (find_what_given) finderror = TRUE;
  21827.          else {
  21828.            find_what = FIND_FIRST;
  21829.            find_what_given = TRUE;
  21830.          }
  21831.        } 
  21832.        else if (EQUAL(temp,"LAST")) {
  21833.          if (find_what_given) finderror = TRUE;
  21834.          else {
  21835.            find_what = FIND_LAST;
  21836.            find_what_given = TRUE;
  21837.          }
  21838.        } 
  21839.        else if (EQUAL(temp,"ALL")) {
  21840.          if (find_what_given) finderror = TRUE;
  21841.          else {
  21842.            find_what = FIND_ALL;
  21843.            find_what_given = TRUE;
  21844.          }
  21845.        } 
  21846.        else if (EQUAL(temp,"CHARS")) {
  21847.          if (find_type_given) finderror = TRUE;
  21848.          else {
  21849.            find_type = FIND_CHARS;
  21850.            find_type_given = TRUE;
  21851.          }
  21852.        } 
  21853.        else if (EQUAL(temp,"WORD")) {
  21854.          if (find_type_given) finderror = TRUE;
  21855.          else {
  21856.            find_type = FIND_WORD;
  21857.            find_type_given = TRUE;
  21858.          }
  21859.        } 
  21860.        else if (EQUAL(temp,"PREFIX") || EQUAL(temp,"PRE")) {
  21861.          if (find_type_given) finderror = TRUE;
  21862.          else {
  21863.            find_type = FIND_PREFIX;
  21864.            find_type_given = TRUE;
  21865.          }
  21866.        } 
  21867.        else if (EQUAL(temp,"SUFFIX") || EQUAL(temp,"SUF")) {
  21868.          if (find_type_given) finderror = TRUE;
  21869.          else {
  21870.            find_type = FIND_SUFFIX;
  21871.            find_type_given = TRUE;
  21872.          }
  21873.        } 
  21874.        else if (*(temp+strspn(temp,"0123456789")) == '\0') {
  21875.          if (find_left_bound_given) {
  21876.            if (find_right_bound_given) finderror = TRUE;
  21877.            else {
  21878.              find_right_bound = atoi(temp);
  21879.              if (find_right_bound > bp->maxlen) out_of_bounds = TRUE;
  21880.              find_right_bound_given = TRUE;
  21881.            }
  21882.          }
  21883.          else {
  21884.            find_left_bound  = atoi(temp);
  21885.              if (find_right_bound < 1) out_of_bounds = TRUE;
  21886.            find_left_bound_given = TRUE;
  21887.          }
  21888.        } 
  21889.        else {
  21890.          if (find_string_given) finderror = TRUE;
  21891.          else {
  21892.            strcpy(find_string,op);
  21893.            find_form = ff;
  21894.            find_string_given = TRUE;
  21895.          }
  21896.        } 
  21897.      }
  21898.    }
  21899.  }
  21900.  
  21901.  if (out_of_bounds) {
  21902.    ERR2("Invalid bound; Bounds must lie between 1 and %d", bp->maxlen);
  21903.    return FALSE;
  21904.  }
  21905.  
  21906.  if (finderror) {
  21907.    ERR1("Put string in quotes; Conflicting or unknown parameter.");
  21908.    return FALSE;
  21909.  }
  21910.  
  21911.  len = strlen(find_string);
  21912.  
  21913.  if (find_string_given) bp->find_hit_end = FALSE;
  21914.  
  21915.  if (find_left_bound_given && find_right_bound_given
  21916.      && find_left_bound > find_right_bound) {
  21917.    n = find_left_bound;
  21918.    find_left_bound = find_right_bound;
  21919.    find_right_bound = n;
  21920.  }
  21921.  else if (find_left_bound_given && !find_right_bound_given) {
  21922.    find_right_bound = find_left_bound + len - 1;
  21923.  }
  21924.  
  21925.  if (find_string_given) {
  21926.    switch (find_form) {
  21927.      case FIND_UNQUOTED:  find_trans = FIND_CAPS;    break;
  21928.      case FIND_QUOTED:    find_trans = FIND_CAPS;    break;
  21929.      case FIND_C:         find_trans = FIND_ASIS;    break;
  21930.      case FIND_T:         find_trans = FIND_CAPS;    break;
  21931.      case FIND_P:         find_trans = FIND_GENERIC; break;
  21932.      case FIND_X:         find_trans = FIND_HEX;
  21933.         if (len % 2 != 0) {
  21934.           ERR1("Odd number of characters in hex string.");
  21935.           return FALSE;
  21936.         }
  21937.         if (len != strspn(find_string,"0123456789abcdefABCDEF")) {
  21938.           ERR1("Invalid (non-hex) characters in hex string.");
  21939.           return FALSE;
  21940.         }
  21941.         for (p = find_string, q = find_string; *p; p += 2, *q++) {
  21942.           sprintf(temp,"0x%2.2s",p);
  21943.           sscanf(temp,"%x",&n);
  21944.           *q = (char)n;
  21945.         }
  21946.         *q = '\0';
  21947.         len = strlen(find_string);
  21948.         break;
  21949.    }
  21950.  }
  21951.  
  21952.  /* Store parameters for next Repeat Find operation. */
  21953.  
  21954.  strcpy(np->text_find_string,find_string);
  21955.  switch (find_what) {
  21956.    case FIND_PREV:
  21957.    case FIND_LAST:  np->text_find_what = FIND_PREV; break;
  21958.    default:         np->text_find_what = FIND_NEXT; break;
  21959.  }
  21960.  np->text_find_type        = find_type;
  21961.  np->text_find_trans       = find_trans;
  21962.  np->text_find_left_bound  = find_left_bound;
  21963.  np->text_find_right_bound = find_right_bound;
  21964.  
  21965.  if (!*find_string) {
  21966.    ERR1("A null string is not allowed for the FIND command.");
  21967.    return FALSE;
  21968.  }
  21969.  
  21970.  if (bp->total == 0) {
  21971.    ERR1("There is no text to search.");
  21972.    return FALSE;
  21973.  }
  21974.  
  21975.  strcpy(bp->zcmd,"");
  21976.  
  21977.  switch (find_type) {
  21978.    case FIND_CHARS:   show_type = "Chars";  break;
  21979.    case FIND_WORD:    show_type = "Word";   break;
  21980.    case FIND_PREFIX:  show_type = "Prefix"; break;
  21981.    case FIND_SUFFIX:  show_type = "Suffix"; break;
  21982.    default:           show_type = "Text";   break;
  21983.  }
  21984.  
  21985.  switch (find_trans) {
  21986.    case FIND_ASIS:    strcpy(show_string+0,"C'");
  21987.                       strcpy(show_string+2,find_string);
  21988.                       strcat(show_string,"'");
  21989.                       break;
  21990.    case FIND_GENERIC: strcpy(show_string+0,"P'");
  21991.                       strcpy(show_string+2,find_string);
  21992.                       strcat(show_string,"'");
  21993.                       break;
  21994.    case FIND_HEX:     strcpy(show_string+0,"X'");
  21995.                       for (p=find_string,q=show_string+2;*p;p++,q+=2) {
  21996.                         sprintf(q,"%2.2X",*p);
  21997.                       }
  21998.                       strcat(show_string,"'");
  21999.                       break;
  22000.    case FIND_CAPS:
  22001.    default:           strcpy(show_string+0,"'");
  22002.                       strcpy(show_string+1,find_string);
  22003.                       strcat(show_string,"'");
  22004.                       break;
  22005.  }
  22006.  
  22007.  switch (find_trans) {
  22008.    case FIND_CAPS:
  22009.         uppercase_in_place(find_string);
  22010.         break;
  22011.    case FIND_GENERIC:
  22012.         ERR1("The P'string' generic format is not supported.");
  22013.         return FALSE;
  22014.  }
  22015.  
  22016.  hit_end = bp->find_hit_end;
  22017.  findlen = strlen(find_string);
  22018.  
  22019.  if (find_what == FIND_ALL) {
  22020.    bp->find_count = 0;
  22021.    if (!find_it(np,bp,find_string,findlen,
  22022.                                   find_type,FIND_FIRST,find_trans,
  22023.                                   find_left_bound, find_right_bound)) {
  22024.      sprintf(shortmsg,"No %s %s found",show_type,show_string);
  22025.      sprintf(longmsg,
  22026.              "%s %s - not found within columns %d to %d",
  22027.              show_type,show_string,find_left_bound,find_right_bound);
  22028.      ERR3("%24s;%s",shortmsg,longmsg);
  22029.      return FALSE;
  22030.    }
  22031.    bp->found_row = bp->find_row;
  22032.    bp->found_col = bp->find_col;
  22033.    bp->find_count = 1;
  22034.    while (find_it(np,bp,find_string,findlen,
  22035.                         find_type,FIND_ALL,find_trans,
  22036.                         find_left_bound, find_right_bound)) {
  22037.          bp->find_count++;
  22038.    }
  22039.    bp->find_hit_end = FALSE;
  22040.  }
  22041.  else {
  22042.    if (!find_it(np,bp,find_string,findlen,
  22043.                                   find_type,find_what,find_trans,
  22044.                                   find_left_bound, find_right_bound)) {
  22045.      if (hit_end) {
  22046.        sprintf(shortmsg,"No %s %s found",show_type,show_string);
  22047.        sprintf(longmsg,
  22048.                "%s %s - not found within columns %d to %d",
  22049.                show_type,show_string,find_left_bound,find_right_bound);
  22050.        ERR3("%24s;%s",shortmsg,longmsg);
  22051.        return FALSE;
  22052.      }
  22053.      else if (np->text_find_what == FIND_PREV) {
  22054.        sprintf(shortmsg,"Top of data reached");
  22055.        sprintf(longmsg,
  22056.             "%s %s not found.  Use RFIND to continue from bottom.",
  22057.              show_type, show_string);
  22058.        ERR3("%24s;%s",shortmsg,longmsg);
  22059.      }
  22060.      else {
  22061.        sprintf(shortmsg,"Bottom of data reached");
  22062.        sprintf(longmsg,
  22063.                "%s %s not found.  Use RFIND to continue from top.",
  22064.              show_type, show_string);
  22065.        ERR3("%24s;%s",shortmsg,longmsg);
  22066.      }
  22067.      return FALSE;
  22068.    }
  22069.    bp->found_row = bp->find_row;
  22070.    bp->found_col = bp->find_col;
  22071.  }
  22072.  
  22073.  if (bp->found_row + 1 < bp->top
  22074.   || bp->found_row + 1 >= bp->top + bp->lvl - bp->cols) {
  22075.    bp->top = bp->found_row + 1 - 1;
  22076.    if (bp->top < 0) bp->top = 0;
  22077.  }
  22078.  
  22079.  if (bp->found_col < bp->coloff) {
  22080.    bp->coloff = bp->found_col;
  22081.    *bp->cols_line = '\0';
  22082.  }
  22083.  else if (bp->found_col+len > bp->coloff+80) {
  22084.    bp->coloff = bp->found_col + len - 80;
  22085.    if (bp->coloff < 0) bp->coloff = 0;
  22086.    *bp->cols_line = '\0';
  22087.  }
  22088.  
  22089.  strcpy(bp->cursor, "NNBDYNA");
  22090.  bp->csrpos = 80 * (bp->found_row - bp->top+bp->cols + 1)
  22091.               + bp->found_col - bp->coloff + 1;
  22092.  
  22093.  bp->found_left = bp->csrpos;
  22094.  bp->found_right = bp->found_left + len;
  22095.  bp->reinit_browse = TRUE;
  22096.  
  22097.  if (find_what == FIND_ALL) {
  22098.    sprintf(shortmsg,"%d %s %s",bp->find_count,show_type,show_string);
  22099.    sprintf(longmsg,
  22100.            "%s %s found %d times within columns %d to %d",
  22101.            show_type,show_string,bp->find_count,
  22102.            find_left_bound,find_right_bound);
  22103.    WARN3("%24s;%s",shortmsg,longmsg);
  22104.  }
  22105.  else {
  22106.    sprintf(shortmsg,"%s %s found",show_type,show_string);
  22107.    sprintf(longmsg,
  22108.            "Search for %s %s within columns %d to %d was successful",
  22109.            show_type,show_string, find_left_bound,find_right_bound);
  22110.    WARN3("%24s;%s",shortmsg,longmsg);
  22111.  }
  22112.  
  22113.  bp->find_row = bp->found_row;
  22114.  bp->find_col = bp->found_col;
  22115.  return TRUE;
  22116. }
  22117.  
  22118. /************ Fill browse dynamic area. *******************************/
  22119.  
  22120. static void
  22121. fill_browse_dynamic_area(np,bp)
  22122. Rstruc nncb        *np;
  22123. Rstruc browser     *bp;
  22124. {
  22125.  struct textline  **tpp  = NULL;
  22126.  register char     *cp   = NULL;
  22127.  register char     *p;
  22128.  char              *q;
  22129.  char              *r;
  22130.  int                i;
  22131.  int                j;
  22132.  char               temp[12];
  22133.  
  22134.  static char  top_of_data_line[81] = "\
  22135. ********************************* Top of data \
  22136. **********************************";
  22137.  
  22138.  static char  bottom_of_data_line[81] = "\
  22139. ******************************** Bottom of data \
  22140. ********************************";
  22141.  
  22142.  bp->lastpos = bp->bda + bp->size;
  22143.  bp->total = bp->thp->text_line_count;
  22144.  
  22145.  memset(bp->bda,' ',bp->size);
  22146.  
  22147.  if      (bp->more_rows == -MAX_INT)
  22148.          bp->top = 0;
  22149.  else if (bp->more_rows == MAX_INT)
  22150.          bp->top = bp->total + 2 - bp->lvl + bp->cols;
  22151.  else    bp->top += bp->more_rows;
  22152.  
  22153.  if (bp->top < 0) bp->top = 0;
  22154.  if (bp->top > bp->total) bp->top = bp->total + 1;
  22155.  
  22156.  i  = bp->top;
  22157.  p  = bp->bda;
  22158.  
  22159.  if (bp->cols > 0) {
  22160.    if (!*bp->cols_line) {
  22161.      for (j=bp->coloff+1,r=bp->cols_line; j<=bp->coloff+80; j++,r++) {
  22162.        if (j%10 == 0) {
  22163.          sprintf(temp,"%d",j%100);
  22164.          *r = temp[0];
  22165.        } 
  22166.        else if (j%5 == 0) *r = '+';
  22167.        else *r = '-';
  22168.      }
  22169.    }
  22170.    memcpy(p,bp->cols_line,80);
  22171.    p += 80;
  22172.  }
  22173.  
  22174.  if (i == 0) {
  22175.    memcpy(p,top_of_data_line,80);
  22176.    p += 80;
  22177.    i++;
  22178.  }
  22179.  
  22180.  bp->firstpos = p;
  22181.  
  22182.  for (tpp=&bp->tv[i-1];i<=bp->total && p<bp->lastpos;i++,tpp++,p+=80) {
  22183.    if ((*tpp)->tab_expanded_text_length > bp->coloff) {
  22184.      cp = (*tpp)->tab_expanded_text + bp->coloff;
  22185.      for (j = 0, q = p; *cp && j < 80; j++, q++, cp++) {
  22186.        if (*cp > 0xf9 || *cp < 0x40) *q = np->text_dispchar;
  22187.        else *q = *cp;
  22188.      }
  22189.    }
  22190.  }
  22191.  
  22192.  if (p < bp->lastpos) {
  22193.    memcpy(p,bottom_of_data_line,80);
  22194.  }
  22195.  
  22196.  return; 
  22197. }
  22198.  
  22199. /************ Highlight browse text. **********************************/
  22200.  
  22201. static void
  22202. highlight_browse_text(np,bp)
  22203. Rstruc nncb        *np;
  22204. Rstruc browser     *bp;
  22205. {
  22206.  char              *p;
  22207.  
  22208.  bp->highlighted = FALSE;
  22209.  
  22210.  if (bp->found_left) {
  22211.    if (EQUAL(bp->cursor,"NNBDYNA")) {
  22212.      for (p = bp->bda + bp->found_left - 1; p >= bp->firstpos; p--) {
  22213.        if (*p == ' ') {
  22214.          *p = DATAOUT_HIGH;
  22215.          bp->highlighted = TRUE;
  22216.          break;
  22217.        } 
  22218.      }
  22219.      for (p = bp->bda + bp->found_right - 1; p <= bp->lastpos; p++) {
  22220.       if (*p == ' ') {
  22221.         *p = DATAOUT_LOW;
  22222.          bp->highlighted = TRUE;
  22223.          break;
  22224.        } 
  22225.      }
  22226.    }
  22227.  }
  22228.  
  22229.  bp->found_left = 0;
  22230.  bp->found_right = 0;
  22231.  
  22232.  return; 
  22233. }
  22234.  
  22235. /************ Display browse data. ************************************/
  22236.  
  22237. static void
  22238. display_browse_data(np,bp,tdp)
  22239. Rstruc nncb        *np;
  22240. Rstruc browser     *bp;
  22241. Rstruc tabledesc   *tdp;
  22242. {
  22243.  Rstruc cmddesc    *cdp;
  22244.  char              *cp;
  22245.  char              *operands;
  22246.  int                displayrc;
  22247.  int                zscrolln;
  22248.  int                leftcol;
  22249.  int                rightcol;
  22250.  int                command_index;
  22251.  Bool               command_processed_ok;
  22252.  Bool               is_max;
  22253.  Bool               is_scroll_word;
  22254.  Bool               is_scroll_cursor;
  22255.  SCROLL             scroll_amount;
  22256.  char               command    [COMMANDSIZE+1];
  22257.  char               zverb      [16];
  22258.  char               zscrolla   [16];
  22259.  char               longmsg    [73];
  22260.  char               nnbtitle   [81];
  22261.  char               nnbmsg     [81];
  22262.  char               temp1      [81];
  22263.  char               temp2      [81];
  22264.  
  22265.  bp->more_rows = 0;
  22266.  bp->override_scroll = FALSE;
  22267.  bp->exit_browse     = FALSE;
  22268.  
  22269.  memset (nnbtitle, '-', 80);
  22270.  strcpy (nnbtitle, "Browse - ");
  22271.  memcpy (nnbtitle + 9, bp->title, strlen(bp->title));
  22272.  
  22273.  if (!np->setmsg) {
  22274.    leftcol = bp->coloff + 1;
  22275.    rightcol = bp->coloff + 80;
  22276.    if (bp->top > bp->total) strcpy(temp1,"");
  22277.    else sprintf(temp1, " Line %d of %d,", bp->top, bp->total);
  22278.    if (bp->maxlen <= 80)
  22279.         sprintf(temp2," Cols %d-%d",leftcol,rightcol);
  22280.    else sprintf(temp2," Cols %d-%d of %d",leftcol,rightcol,bp->maxlen);
  22281.    strcpy(nnbmsg,temp1);
  22282.    strcat(nnbmsg,temp2);
  22283.    strcpy (nnbtitle + 79 - strlen(nnbmsg), nnbmsg);
  22284.  }
  22285.  
  22286.  (void)NNMivput(np,"NNBTITLE ",nnbtitle    ,-1);
  22287.  (void)NNMivput(np,"ZCMD "    ,bp->zcmd    ,-1);
  22288.  (void)NNMivput(np,"NNBDYNA " ,bp->bda     ,bp->size);
  22289.  (void)NNMivput(np,"NNBCUR "  ,bp->cursor  ,-1);
  22290.  sprintf(temp1,"%d",bp->csrpos);
  22291.  (void)NNMivput(np,"NNBPOS  " ,temp1       ,-1);
  22292.  (void)NNMivput(np,"YRFIND "  ,"ALIAS FIND",-1);
  22293.  
  22294.  displayrc = NNMdispl(np,"NNMVIEW ");
  22295.  
  22296.  if (displayrc > 0) bp->exit_browse = TRUE;
  22297.  
  22298.  (void)NNMivput(np,"YRFIND "  ,"",-1);
  22299.  (void)NNMivget(np,"NNBCUR  " ,bp->cursor  , 8);
  22300.  (void)NNMivget(np,"ZCMD    " ,bp->zcmd     ,sizeof(bp->zcmd));
  22301.  bp->lvl    = NNMiget(np,"NNBLVL  ");
  22302.  bp->csrpos = NNMiget(np,"NNBPOS  ");
  22303.  
  22304.  strip_trailing_in_place(bp->cursor); /* try to fix UCLA find bug */
  22305.  
  22306.  strcpy(bp->find_cursor, bp->cursor);
  22307.  bp->find_csrpos = bp->csrpos;
  22308.  strcpy(bp->cursor,"");
  22309.  bp->csrpos = 1;
  22310.  if (bp->highlighted) bp->reinit_browse = TRUE;
  22311.  else                 bp->reinit_browse = FALSE;
  22312.  
  22313.  if (*bp->zcmd) {
  22314.  
  22315.    memset(command,' ',COMMANDSIZE);
  22316.    command_index = 0;
  22317.    for (cp = bp->zcmd; *cp && !isspace(*cp); cp++) {
  22318.      if (cp >= bp->zcmd+COMMANDSIZE) {
  22319.        ERR1("Unknown command name.");
  22320.        command_processed_ok = FALSE;
  22321.      }
  22322.      command[command_index++] = toupper(*cp);
  22323.    }
  22324.    while (*cp && isspace(*cp)) cp++;
  22325.  
  22326.    for (cdp=tdp->first_cmddesc; *cdp->command_name != ' '; cdp++) {
  22327.      if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  22328.        command_processed_ok = (cdp->command_processor)(np,bp,cp);
  22329.        cdp = NULL;
  22330.        break;
  22331.      }
  22332.      #define LASTAPCMD "OPT "
  22333.      #define LASTAPLEN 4
  22334.      else if (!bp->ap
  22335.            && !memcmp(cdp->command_name,LASTAPCMD,LASTAPLEN))
  22336.               break;
  22337.    }
  22338.    if (cdp) {
  22339.      for (cdp=tdp->next_cmddesc; *cdp->command_name != ' '; cdp++) {
  22340.        if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  22341.          command_processed_ok = (cdp->command_processor)(np,bp,cp);
  22342.          cdp = NULL;
  22343.          break;
  22344.        } 
  22345.      }
  22346.    }
  22347.    if (cdp) {
  22348.      ERR1("Unknown command name.");
  22349.      command_processed_ok = FALSE;
  22350.    }
  22351.  
  22352.    if (command_processed_ok) strcpy(bp->zcmd,"");
  22353.  
  22354.  }
  22355.  
  22356.  if (np->quit || bp->exit_browse) return;
  22357.  
  22358.  /* Check scroll request (ZSCROLLA direction, ZSCROLLN number).
  22359.   * Skip this if something was done by a command which causes
  22360.   * its own pseudo-scrolling to happen (like LOCATE).
  22361.   */
  22362.  
  22363.  if (!bp->override_scroll) {
  22364.  
  22365.    zscrolln = 0;
  22366.  
  22367.    (void)NNMivget(np,"ZVERB    " ,  zverb    ,sizeof(zverb));
  22368.    (void)NNMivget(np,"ZSCROLLA " ,  zscrolla ,sizeof(zscrolla));
  22369.    zscrolln = NNMiget(np,"ZSCROLLN ");
  22370.  
  22371.    is_max = FALSE;
  22372.    is_scroll_word = FALSE;
  22373.    is_scroll_cursor = FALSE;
  22374.  
  22375.    switch (zscrolla[0]) {
  22376.      case 'P':
  22377.      case 'H':
  22378.      case 'D':  is_scroll_word = TRUE;
  22379.                 break;
  22380.      case 'C':  is_scroll_word = TRUE;
  22381.                 is_scroll_cursor = TRUE;
  22382.                 break;
  22383.      case 'M':  is_max = TRUE;
  22384.                 break;
  22385.    }
  22386.  
  22387.    if      (EQUAL(zverb,"DOWN"))  scroll_amount = DOWN;
  22388.    else if (EQUAL(zverb,"UP"))    scroll_amount = UP;
  22389.    else if (EQUAL(zverb,"LEFT"))  scroll_amount = LEFT;
  22390.    else if (EQUAL(zverb,"RIGHT")) scroll_amount = RIGHT;
  22391.    else                           scroll_amount = NO_SCROLL;
  22392.  
  22393.  
  22394.    switch (scroll_amount) {
  22395.      case NO_SCROLL:
  22396.           bp->more_rows = 0;
  22397.           break;
  22398.      case DOWN:
  22399.           if (is_max) bp->more_rows = MAX_INT;
  22400.           else if (is_scroll_word)
  22401.                       bp->more_rows = zscrolln - bp->cols;
  22402.           else        bp->more_rows = zscrolln;
  22403.           bp->reinit_browse = TRUE;
  22404.           break;
  22405.      case UP:
  22406.           if (is_max) bp->more_rows = -MAX_INT;
  22407.           else if (is_scroll_cursor)
  22408.                       bp->more_rows = -zscrolln;
  22409.           else if (is_scroll_word)
  22410.                       bp->more_rows = -zscrolln - bp->cols;
  22411.           else        bp->more_rows = -zscrolln;
  22412.           bp->reinit_browse = TRUE;
  22413.           break;
  22414.      case LEFT:
  22415.           if (is_max) bp->coloff = 0;
  22416.           else        bp->coloff -= zscrolln;
  22417.           if (bp->coloff < 0) bp->coloff = 0;
  22418.           *bp->cols_line = '\0';
  22419.           bp->more_rows = 0;
  22420.           bp->reinit_browse = TRUE;
  22421.           break;
  22422.      case RIGHT:
  22423.           if (is_max) bp->coloff = bp->maxcoloff;
  22424.           else        bp->coloff += zscrolln;
  22425.           if (bp->coloff > bp->maxcoloff) bp->coloff = bp->maxcoloff;
  22426.           *bp->cols_line = '\0';
  22427.           bp->more_rows = 0;
  22428.           bp->reinit_browse = TRUE;
  22429.           break;
  22430.    }
  22431.  }
  22432.  
  22433.  return; 
  22434. }
  22435.  
  22436. /*---*/
  22437.  
  22438. static struct cmddesc browse_commands[] = {
  22439.                           {"L          ",process_locate_command   },
  22440.                           {"LOC        ",process_locate_command   },
  22441.                           {"LOCATE     ",process_locate_command   },
  22442.                           {"F          ",process_find_command     },
  22443.                           {"FIND       ",process_find_command     },
  22444.                           {"RFIND      ",process_find_command     },
  22445.                           {"YRFIND     ",process_find_command     },
  22446.                           {"COL        ",process_cols_command     },
  22447.                           {"COLS       ",process_cols_command     },
  22448.                           {"RES        ",process_reset_command    },
  22449.                           {"RESET      ",process_reset_command    },
  22450.                           {"NOCOL      ",process_reset_command    },
  22451.                           {"NOCOLS     ",process_reset_command    },
  22452.                           {"DISP       ",process_display_command  },
  22453.                           {"DISPL      ",process_display_command  },
  22454.                           {"DISPLAY    ",process_display_command  },
  22455.                           {"EXT        ",process_extract_command  },
  22456.                           {"EXTR       ",process_extract_command  },
  22457.                           {"EXTRACT    ",process_extract_command  },
  22458.                           {"PRT        ",process_print_command    },
  22459.                           {"PRNT       ",process_print_command    },
  22460.                           {"PRINT      ",process_print_command    },
  22461.                           {"ROT13      ",process_rot13_command    },
  22462.  /* overrides general */  {"OPTIONS    ",process_options_command  },
  22463.  /* overrides general */  {"OPT        ",process_options_command  },
  22464.  /* overrides general */  {"HEADERS    ",process_headers_command  },
  22465.  /* overrides general */  {"HEADER     ",process_headers_command  },
  22466.                           {"UNREAD     ",process_unread_command   },
  22467.                           {"REPLY      ",process_reply_command    },
  22468.                           {"FOLLOWUP   ",process_followup_command },
  22469.                           {"NEXT       ",process_next_command     },
  22470.                           {"PREV       ",process_prev_command     },
  22471.                           {"NEXTU      ",process_nextu_command    },
  22472.                           {"NU         ",process_nextu_command    },
  22473.                           {"PREVU      ",process_prevu_command    },
  22474.                           {"PU         ",process_prevu_command    },
  22475.                           {"NEXTT      ",process_nextt_command    },
  22476.                           {"NT         ",process_nextt_command    },
  22477.                           {"PREVT      ",process_prevt_command    },
  22478.                           {"PT         ",process_prevt_command    },
  22479.                           {"NEXTS      ",process_nextsubj_command },
  22480.                           {"NEXTSUBJ   ",process_nextsubj_command },
  22481.                           {"NS         ",process_nextsubj_command },
  22482.                           {"PREVS      ",process_prevsubj_command },
  22483.                           {"PREVSUBJ   ",process_prevsubj_command },
  22484.                           {"PS         ",process_prevsubj_command },
  22485.                           {"FIRSTS     ",process_firstsubj_command},
  22486.                           {"FIRSTSUBJ  ",process_firstsubj_command},
  22487.                           {"FS         ",process_firstsubj_command},
  22488.                           {"LASTS      ",process_lastsubj_command },
  22489.                           {"LASTSUBJ   ",process_lastsubj_command },
  22490.                           {"LS         ",process_lastsubj_command },
  22491.                           {"NEWSUBJ    ",process_newsubj_command  },
  22492.                           {"SUBJECT    ",process_subject_command  },
  22493.                           {"SUBJ       ",process_subject_command  },
  22494.                           {"           ",NULL}
  22495.                          };
  22496.  
  22497.  
  22498. /****** View text in full screen mode (BROWSE replacement) ***********/
  22499.  
  22500. void
  22501. NNMview(np,gp,ap,texthdrp,title)
  22502. Rstruc nncb         *np;
  22503. Rstruc newsgroup    *gp;
  22504. Rstruc newsarticle  *ap;
  22505. struct texthdr      *texthdrp;
  22506. char                *title;
  22507. {
  22508.  Rstruc tabledesc   *tdp;
  22509.  struct textline    *tp;
  22510.  struct textline   **tv;
  22511.  struct textline   **textvector;
  22512.  struct browser     *bp;
  22513.  struct browser      browserstruct;
  22514.  
  22515.  GETMAIN(textvector, struct textline *,
  22516.          texthdrp->text_line_count, "text vector");
  22517.  if (!textvector) {
  22518.    ERR1("Not enough memory to display text.");
  22519.    return;
  22520.  }
  22521.  
  22522.  bp = &browserstruct;
  22523.  memset(bp,0,sizeof(struct browser));
  22524.  bp->gp = gp;
  22525.  bp->ap = ap;
  22526.  bp->thp = texthdrp;
  22527.  bp->tv = textvector;
  22528.  strcpy(bp->title,title);
  22529.  bp->more_rows = -MAX_INT;   /* set initial request to scroll up max */
  22530.  bp->top       = 0;
  22531.  bp->find_row  = -1;
  22532.  bp->find_col  = -1;
  22533.  bp->csrpos    = 1;
  22534.  strcpy(bp->cursor,"");
  22535.  bp->reinit_browse = TRUE;
  22536.  
  22537.  /* Collect text line pointers, skipping suppressed lines. */
  22538.  
  22539.  bp->maxlen = 0;
  22540.  for (tp=texthdrp->first_text_line, tv=textvector; tp; tp=tp->next) {
  22541.    if (tp->text_length >= 0) {
  22542.      *(tv++) = tp;
  22543.      if (bp->maxlen < tp->tab_expanded_text_length)
  22544.          bp->maxlen = tp->tab_expanded_text_length;
  22545.    }
  22546.  }
  22547.  bp->maxcoloff = bp->maxlen - 80;
  22548.  if (bp->maxcoloff < 0) bp->maxcoloff = 0;
  22549.  
  22550.  GETMAIN(bp->work, char *, bp->maxlen+1, "browse work string");
  22551.  if (!bp->work) return;
  22552.  
  22553.  (void)NNMispf(np,
  22554.          "PQUERY PANEL(NNMVIEW) AREANAME(NNBDYNA) DEPTH(NNBDEPTH)");
  22555.  if (np->ispfrc != 0) return;
  22556.  bp->depth = NNMiget(np,"NNBDEPTH ");
  22557.  bp->size = bp->depth * 80;
  22558.  GETMAIN(bp->bda, char *, bp->size+1, "browse dynamic area");
  22559.  if (!bp->bda) return;
  22560.  
  22561.  if (!np->text_dispchar) np->text_dispchar = '.';
  22562.  
  22563.  tdp = np->display_table_vector->text_display_table;
  22564.  tdp->first_cmddesc = browse_commands;
  22565.  
  22566.  for (;;) {
  22567.    if (bp->reinit_browse) {
  22568.      fill_browse_dynamic_area(np,bp);
  22569.      highlight_browse_text(np,bp);
  22570.    }
  22571.    display_browse_data(np,bp,tdp);
  22572.    if (np->quit || bp->exit_browse) break;
  22573.  }
  22574.  
  22575.  FREEMAIN(bp->work,"browse work string");
  22576.  FREEMAIN(bp->bda,"browse dynamic area");
  22577.  FREEMAIN(textvector, "text vector");
  22578.  
  22579.  return; 
  22580. }
  22581.  
  22582. ./   ADD NAME=NNMVNG,SSI=01110006
  22583.  
  22584.  /********************************************************************/
  22585.  /*                                                                  */
  22586.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  22587.  /*                                                                  */
  22588.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  22589.  /*                                                                  */
  22590.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  22591.  /* including the implied warranties of merchantability and fitness, */
  22592.  /* are expressly denied.                                            */
  22593.  /*                                                                  */
  22594.  /* Provided this copyright notice is included, this software may    */
  22595.  /* be freely distributed and not offered for sale.                  */
  22596.  /*                                                                  */
  22597.  /* Changes or modifications may be made and used only by the maker  */
  22598.  /* of same, and not further distributed.  Such modifications should */
  22599.  /* be mailed to the author for consideration for addition to the    */
  22600.  /* software and incorporation in subsequent releases.               */
  22601.  /*                                                                  */
  22602.  /********************************************************************/
  22603.  
  22604. #pragma  csect(code,  "NN@VNG  ")
  22605. #pragma  csect(static,"NN$VNG  ")
  22606. #include "nn.h"
  22607.  
  22608. struct ngdynarray {
  22609.                    struct newsgroup      *newsgroup;
  22610.                   };
  22611.  
  22612. /****** Display newsgroups via ISPF dynamic area. ********************/
  22613.  
  22614. Bool
  22615. NNMvng(np)
  22616. Rstruc nncb           *np;
  22617. {
  22618.  Rstruc newsgroup     *gp;
  22619.  Rstruc ngdynarray    *ndp;
  22620.  struct ngdynarray    *ngdynarray_address;
  22621.  Rstruc tabledesc     *tdp;
  22622.  Rstruc seldesc       *sdp;
  22623.  Rstruc cmddesc       *cdp;
  22624.  char                 *cp;
  22625.  int                   next_offset;
  22626.  int                   command_index;
  22627.  int                   newsgroup_count;
  22628.  int                   display_total;
  22629.  int                   dti;
  22630.  int                   ngi;
  22631.  int                   prc;
  22632.  int                   nnglvl;
  22633.  int                   depth;
  22634.  int                   topgroup;
  22635.  int                   bottomgroup;
  22636.  int                   save_topgroup;
  22637.  int                   last_group_located;
  22638.  int                   last_group_selected;
  22639.  int                   groupcursor;
  22640.  int                   zscrolln;
  22641.  int                   dynsize;
  22642.  int                   framelength;
  22643.  int                   findbump;
  22644.  short                 name_length;
  22645.  Bool                  is_max;
  22646.  Bool                  selection_processed_ok;
  22647.  Bool                  command_processed_ok;
  22648.  Bool                  text_not_found;
  22649.  char                 *rowp;
  22650.  char                 *nngdyna;
  22651.  char                  sel;
  22652.  char                  tcmd     [72];
  22653.  char                  nnghead  [81];
  22654.  char                  nngline  [81];
  22655.  char                  nngcsr   [12];
  22656.  char                  command  [COMMANDSIZE];
  22657.  char                  zverb     [9];
  22658.  char                  zscrolla  [9];
  22659.  char                  rowmessage[81];
  22660.  
  22661.  static char           dashes[65] =
  22662.     "----------------------------------------------------------------";
  22663.  
  22664.  tdp = np->display_table_vector->newsgroup_display_table;
  22665.  
  22666.  np->current_newsgroup           = NULL;
  22667.  np->newsgroup_selected          = FALSE;
  22668.  np->newsgroup_criterion_changed = TRUE;
  22669.  np->newsgroup_order_changed     = TRUE;
  22670.  text_not_found                  = FALSE;
  22671.  strcpy(np->newsgroup_only_string,"");
  22672.  
  22673.  /* Determine how many TOTAL newsgroups we have. */
  22674.  
  22675.  newsgroup_count = 0;
  22676.  for (gp = np->first_newsgroup; gp; gp = gp->next) newsgroup_count++;
  22677.  
  22678.  /* Allocate a block of "ngdynarray" newsgroup pointers, one element
  22679.   * for each newsgroup that is currently displayed.  This must be
  22680.   * big enough to hold all known newsgroups at maximum.
  22681.   */
  22682.  
  22683.  if (newsgroup_count == 0) {
  22684.    ERR1( 
  22685.      "No newsgroups to display.  Use L option to get list from server."
  22686.        );
  22687.    return FALSE;
  22688.  }
  22689.  
  22690.  GETMAIN(ngdynarray_address, struct ngdynarray,
  22691.          newsgroup_count, "newsgroup dynamic array");
  22692.  if (!ngdynarray_address) return FALSE;
  22693.  
  22694.  /* Get depth of dynamic area (number of rows to display on screen) */
  22695.  
  22696.  (void)NNMispf(np,
  22697.        "PQUERY PANEL(NNMDNG) AREANAME(NNGDYNA) DEPTH(NNGDEPTH)");
  22698.  if (np->ispfrc != 0) return FALSE;
  22699.  depth = NNMiget(np,"NNGDEPTH ");
  22700.  
  22701.  /* Get storage for ISPF dynamic area variable to be constructed. */
  22702.  
  22703.  dynsize = 80*depth;
  22704.  GETMAIN(nngdyna, char, dynsize+1, "NNGDYNA buffer");
  22705.  if (!nngdyna) return FALSE;
  22706.  memset(nngdyna,' ',dynsize);
  22707.  
  22708.  topgroup = 0;
  22709.  groupcursor = 0;
  22710.  last_group_located  = -1;
  22711.  last_group_selected = -1;
  22712.  
  22713.  strcpy(tcmd,"");
  22714.  
  22715.  memset(nngline,' ',80);
  22716.  nngline[ 0] = DATAOUT_HIGH;
  22717.  nngline[ 1] = 'S';
  22718.  nngline[ 2] = DATAOUT_LOW;
  22719.  memcpy(&nngline[ 3],"select",6);
  22720.  nngline[ 9] = DATAOUT_HIGH;
  22721.  nngline[10] = 'A';
  22722.  nngline[11] = DATAOUT_LOW;
  22723.  memcpy(&nngline[12],"all",   3);
  22724.  nngline[15] = DATAOUT_HIGH;
  22725.  nngline[16] = 'R';
  22726.  nngline[17] = DATAOUT_LOW;
  22727.  memcpy(&nngline[18],"reg",   3);
  22728.  nngline[21] = DATAOUT_HIGH;
  22729.  nngline[22] = 'D';
  22730.  nngline[23] = DATAOUT_LOW;
  22731.  memcpy(&nngline[24],"dereg", 5);
  22732.  nngline[29] = DATAOUT_HIGH;
  22733.  nngline[30] = 'M';
  22734.  nngline[31] = DATAOUT_LOW;
  22735.  memcpy(&nngline[32],"mark",  4);
  22736.  nngline[36] = DATAOUT_HIGH;
  22737.  nngline[37] = 'U';
  22738.  nngline[38] = DATAOUT_LOW;
  22739.  memcpy(&nngline[39],"unmark",6);
  22740.  nngline[48] = DATAOUT_HIGH;
  22741.  strcpy(&nngline[49],"Unread   Count   Range");
  22742.  
  22743.  /* The last line above may be variable some day if we have to vary
  22744.     the width of the numbers...  */
  22745.  
  22746.  /* Loop displaying newsgroups until END or criterion changed. */
  22747.  
  22748.  do {
  22749.  
  22750.    /* If the newsgroup display criteria have changed, or this is the
  22751.       first time through, build the array of newsgroup pointers.  */
  22752.  
  22753.    if (np->newsgroup_criterion_changed || np->newsgroup_order_changed) {
  22754.      ndp = ngdynarray_address;
  22755.      display_total = 0;
  22756.      topgroup = 0;
  22757.      switch (np->newsgroup_order) {
  22758.        case NNTP_LIST_ORDER:
  22759.             gp = np->first_newsgroup_alt;
  22760.             next_offset = (char *)&gp->next2 - (char *)gp;
  22761.             break;
  22762.        case ALPHABETICAL_ORDER:
  22763.        default:
  22764.             gp = np->first_newsgroup;
  22765.             next_offset = (char *)&gp->next - (char *)gp;
  22766.             break;
  22767.      }
  22768.      for (; gp; gp = *(struct newsgroup **)((int)gp + next_offset)) {
  22769.        if (np->newsgroup_criterion_changed) {
  22770.          OffGroupInTable(gp);   /* guilty until proven innocent */
  22771.          if ((np->show_all_newsgroups && !NoSuchGroup(gp))
  22772.           || gp->registered) {
  22773.            if (!*np->newsgroup_only_string
  22774.             || strstr(gp->name,np->newsgroup_only_string)) {
  22775.              SetGroupInTable(gp);
  22776.            }
  22777.          }
  22778.        } 
  22779.        if (GroupInTable(gp)) {
  22780.          display_total++;
  22781.          ndp->newsgroup = gp;
  22782.          ndp++;
  22783.        } 
  22784.      }
  22785.    }
  22786.  
  22787.    np->newsgroup_criterion_changed = FALSE;
  22788.    np->newsgroup_order_changed     = FALSE;
  22789.  
  22790.    /* Fill dynamic area with data for groups satisfying criterion. */
  22791.  
  22792.    memset(nngdyna, ' ', dynsize);
  22793.  
  22794.    for (dti = 0,       ngi = topgroup,        rowp = nngdyna;
  22795.         dti < depth && ngi < display_total;
  22796.         dti++,         ngi++,                 rowp += 80) {
  22797.      ndp = &ngdynarray_address[ngi];
  22798.      gp  = ndp->newsgroup;
  22799.      rowp[ 0]  = DATAIN_HIGH;     /* selection code attribute */
  22800.      rowp[ 1]  = ' ';             /* selection code field     */
  22801.      rowp[ 2]  = gp->registered
  22802.                  ? (gp->unread_count ? DATAOUT_YELLOW : DATAOUT_TURQ)
  22803.                  : (gp->unread_count ? DATAOUT_GREEN  : DATAOUT_BLUE);
  22804.                                       /* newsgroup name attribute */
  22805.      memset(&rowp[3], '.', 40);
  22806.      name_length = strlen(gp->name);
  22807.      if (name_length > 40) name_length = 40;
  22808.      memcpy(&rowp[3], gp->name, name_length);
  22809.      rowp[3+name_length] = DATAOUT_BLUE;
  22810.      rowp[43] = DATAOUT_PINK;
  22811.      rowp[44] = gp->registered ? 'R' : ' ';
  22812.      rowp[45] = DATAOUT_HIGH;
  22813.      if (gp->unread_count != 0)
  22814.         sprintf(&rowp[46], "  %7d", gp->unread_count);
  22815.      rowp[55] = DATAOUT_LOW;
  22816.      if (gp->article_count == 0)
  22817.         strcpy(&rowp[56],"      0                ");
  22818.      else
  22819.         sprintf(&rowp[56], "%7d %7d -%7d",
  22820.                 gp->article_count, gp->low_number, gp->high_number);
  22821.      rowp[strlen(rowp)] = ' ';
  22822.  
  22823.      if (NoSuchGroup(gp)) {
  22824.        memcpy(&rowp[46],"******* No such newsgroup *******",33);
  22825.      }
  22826.  
  22827.    }
  22828.  
  22829.    if (rowp < nngdyna + dynsize) {
  22830.      rowp[0] = DATAOUT_HIGH;
  22831.      memset(&rowp[1], '-',79);
  22832.    }
  22833.  
  22834.    bottomgroup = ngi - 1;
  22835.  
  22836.    if (topgroup > bottomgroup) strcpy(rowmessage,"");
  22837.    else sprintf(rowmessage, "%d-%d of %d",
  22838.                        topgroup + 1, bottomgroup + 1, display_total);
  22839.  
  22840.  
  22841.    framelength = (79 - strlen(rowmessage) - sizeof("Newsgroup Listing")
  22842.                  - 3) / 2;
  22843.  
  22844.    sprintf(nnghead, "%*.*s Newsgroup Listing %*.*s %s",
  22845.                     framelength, framelength, dashes,
  22846.                     framelength, framelength, dashes,
  22847.                     rowmessage);
  22848.  
  22849.    if (last_group_selected >= 0 && np->newsgroup_autocursor) {
  22850.      groupcursor = (last_group_selected - topgroup) * 80 + 2;
  22851.    }
  22852.  
  22853.    if (groupcursor > 0) {
  22854.      sprintf(nngcsr,"%d",groupcursor);
  22855.      (void)NNMivput(np,"NNGCSR ", nngcsr, -1);
  22856.    }
  22857.    else {
  22858.      (void)NNMivput(np,"NNGCSR ", "0", 1);
  22859.    }
  22860.  
  22861.    (void)NNMivput(np,"NNGCMD ",  tcmd,    -1);
  22862.    (void)NNMivput(np,"NNGHEAD ", nnghead, -1);
  22863.    (void)NNMivput(np,"NNGLINE ", nngline, -1);
  22864.    (void)NNMivput(np,"NNGDYNA ", nngdyna, dynsize);
  22865.    (void)NNMivput(np,"YRFIND " , "ALIAS FIND",-1);
  22866.  
  22867.    prc = NNMdispl(np,"NNMDNG  ");
  22868.    if (prc > 8) break;
  22869.  
  22870.    /* (void)NNMispf(np,"VGET (ZVERB ZSCROLLA ZSCROLLN)"); */
  22871.  
  22872.    (void)NNMivput(np,"YRFIND "  ,"",-1);
  22873.    (void)NNMivget(np,"NNGDYNA " , nngdyna,  dynsize);
  22874.    (void)NNMivget(np,"ZVERB "   , zverb,    sizeof(zverb));
  22875.    (void)NNMivget(np,"ZSCROLLA ", zscrolla, sizeof(zscrolla));
  22876.    zscrolln = NNMiget(np,"ZSCROLLN ");
  22877.    nnglvl   = NNMiget(np,"NNGLVL ");
  22878.  
  22879.    /* Initialize what may be set by selection/command processors. */
  22880.  
  22881.    strcpy(np->nngroup,"");
  22882.    last_group_selected = -1;
  22883.    last_group_located  = -1;
  22884.    groupcursor = 0;
  22885.    np->please_locate_group = FALSE;
  22886.    np->please_find_group   = FALSE;
  22887.  
  22888.    /* Process selections. */
  22889.  
  22890.    for (ngi = topgroup,        rowp = nngdyna;
  22891.         ngi <= bottomgroup  && !np->quit;
  22892.         ngi++,                 rowp += 80) {
  22893.      ndp = &ngdynarray_address[ngi];
  22894.      gp = ndp->newsgroup;
  22895.      sel = toupper(rowp[1]);
  22896.      if (sel == ' ') continue;
  22897.      for (sdp = tdp->first_seldesc; sdp->selection_code != ' '; sdp++) {
  22898.        if (sel == sdp->selection_code) {
  22899.          (void)NNMivput(np,"NNGNAME ",gp->name, -1);
  22900.          selection_processed_ok = (sdp->selection_processor)(np,gp);
  22901.          sdp = NULL;
  22902.          break;
  22903.        } 
  22904.      }
  22905.      if (sdp) {
  22906.        ERR1("Unknown selection code.  Type one of the listed codes.");
  22907.        selection_processed_ok = FALSE;
  22908.      }
  22909.      else if (selection_processed_ok) {
  22910.        if (*np->nngroup) last_group_located = ngi;
  22911.        if (np->newsgroup_autocursor) last_group_selected = ngi;
  22912.      }
  22913.    }
  22914.  
  22915.    if (np->quit) break;
  22916.  
  22917.    /* Process command if any. */
  22918.  
  22919.    strcpy(tcmd,"");
  22920.  
  22921.    (void)NNMivget(np,tdp->command_variable,tcmd,sizeof(tcmd));
  22922.  
  22923.    if (strcmp(tcmd,"") != 0) {
  22924.  
  22925.      memset(command,' ',COMMANDSIZE);
  22926.      command_index = 0;
  22927.      for (cp = tcmd; *cp && !isspace(*cp); cp++) {
  22928.        if (cp >= tcmd+COMMANDSIZE) {
  22929.          ERR1("Unknown command name.");
  22930.          command_processed_ok = FALSE;
  22931.        } 
  22932.        command[command_index++] = toupper(*cp);
  22933.      }
  22934.      while (*cp && isspace(*cp)) cp++;
  22935.  
  22936.      for (cdp=tdp->first_cmddesc; cdp->command_name[0] != ' '; cdp++) {
  22937.        if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  22938.          command_processed_ok = (cdp->command_processor)(np,NULL,cp);
  22939.          cdp = NULL;
  22940.          break;
  22941.        } 
  22942.      }
  22943.      if (cdp) {
  22944.        for (cdp=tdp->next_cmddesc; cdp->command_name[0] != ' '; cdp++) {
  22945.          if (!memcmp(command,cdp->command_name,COMMANDSIZE-1)) {
  22946.            command_processed_ok = (cdp->command_processor)(np,NULL,cp);
  22947.            cdp = NULL;
  22948.            break;
  22949.          }
  22950.        } 
  22951.      }
  22952.  
  22953.      if (cdp) {
  22954.        ERR1("Unknown command name.");
  22955.        command_processed_ok = FALSE;
  22956.      }
  22957.  
  22958.      if (command_processed_ok) strcpy(tcmd,"");
  22959.  
  22960.    }
  22961.  
  22962.    if (np->quit) break;
  22963.  
  22964.    /* If locate to a specific group name was requested,
  22965.       process before any scroll request.  */
  22966.  
  22967.    if (last_group_located >= 0 && np->newsgroup_autoscroll) {
  22968.      text_not_found = FALSE;
  22969.      topgroup = last_group_located;
  22970.    }
  22971.    else if (np->please_locate_group) {
  22972.      text_not_found = FALSE;
  22973.      for (topgroup = 0, ndp = ngdynarray_address;
  22974.           topgroup < display_total;
  22975.           topgroup++,   ndp++) {
  22976.        gp = ndp->newsgroup;
  22977.        if (strcmp(gp->name,np->newsgroup_locate_string) >= 0) break;
  22978.      }
  22979.      if (topgroup == display_total) topgroup--;
  22980.    }
  22981.    else if (np->please_find_group) {
  22982.      save_topgroup = topgroup;
  22983.      switch (np->newsgroup_find_option) {
  22984.        case FIND_NEXT:
  22985.                        findbump = 1;
  22986.                        if (np->repeat_find) {
  22987.                          if (text_not_found) topgroup = 0;
  22988.                          else topgroup++;
  22989.                        }
  22990.                        break;
  22991.        case FIND_PREV:
  22992.                        findbump = -1;
  22993.                        if (np->repeat_find) {
  22994.                          if (text_not_found) topgroup = bottomgroup;
  22995.                          else topgroup--;
  22996.                        }
  22997.                        break;
  22998.        case FIND_FIRST:
  22999.                        topgroup = 0;
  23000.                        findbump = 1;
  23001.                        break;
  23002.        case FIND_LAST:
  23003.                        topgroup = display_total - 1;
  23004.                        findbump = -1;
  23005.                        break;
  23006.      }
  23007.      gp = NULL;
  23008.      for (ndp = &ngdynarray_address[topgroup];
  23009.           topgroup < display_total && topgroup >= 0;
  23010.           topgroup += findbump, ndp += findbump) {
  23011.        if (GroupInTable(ndp->newsgroup)
  23012.         && strstr(ndp->newsgroup->name,np->newsgroup_find_string)) {
  23013.          gp = ndp->newsgroup;
  23014.          break;
  23015.        } 
  23016.      }
  23017.      if (!gp) {
  23018.        topgroup = save_topgroup;
  23019.        text_not_found = TRUE;
  23020.        ERR3("No %s newsgroups with '%s' in name.",
  23021.             (findbump > 0 ? "more" : "previous"),
  23022.             np->newsgroup_find_string);
  23023.      }
  23024.      else {
  23025.        text_not_found = FALSE;
  23026.    WARN1("Newsgroup found;\
  23027. The newsgroup whose name contains the desired text tops the display.");
  23028.      }
  23029.    }
  23030.    else text_not_found = FALSE;
  23031.  
  23032.    /* Process scroll request if any. */
  23033.  
  23034.    is_max = EQUAL(zscrolla,"MAX");
  23035.    if      (EQUAL(zverb,"DOWN")) {
  23036.      if (is_max) topgroup = display_total - nnglvl + 1;
  23037.      else        topgroup += zscrolln;
  23038.    }
  23039.    else if (EQUAL(zverb,"UP")) {
  23040.      if (is_max) topgroup = 0;
  23041.      else        topgroup -= zscrolln;
  23042.    }
  23043.    if (topgroup < 0)
  23044.        topgroup = 0;
  23045.    if (topgroup > display_total)
  23046.        topgroup = display_total;
  23047.  
  23048.  } while (prc == 0);
  23049.  
  23050.  FREEMAIN(nngdyna,"NNGDYNA buffer");
  23051.  FREEMAIN(ngdynarray_address,"newsgroup dynamic area");
  23052.  
  23053.  return TRUE;
  23054.  
  23055. }
  23056.  
  23057. ./   ADD NAME=NNMVTX,SSI=01030005
  23058.  
  23059.  /********************************************************************/
  23060.  /*                                                                  */
  23061.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  23062.  /*                                                                  */
  23063.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  23064.  /*                                                                  */
  23065.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  23066.  /* including the implied warranties of merchantability and fitness, */
  23067.  /* are expressly denied.                                            */
  23068.  /*                                                                  */
  23069.  /* Provided this copyright notice is included, this software may    */
  23070.  /* be freely distributed and not offered for sale.                  */
  23071.  /*                                                                  */
  23072.  /* Changes or modifications may be made and used only by the maker  */
  23073.  /* of same, and not further distributed.  Such modifications should */
  23074.  /* be mailed to the author for consideration for addition to the    */
  23075.  /* software and incorporation in subsequent releases.               */
  23076.  /*                                                                  */
  23077.  /********************************************************************/
  23078.  
  23079. #pragma  csect(code,  "NN@VTX  ")
  23080. #pragma  csect(static,"NN$VTX  ")
  23081. #include "nn.h"
  23082.  
  23083. /****** View the lines of text retrieved from the server. ************/
  23084.  
  23085. void
  23086. NNMvtx(np,gp,ap)
  23087. Rstruc nncb         *np;
  23088. Rstruc newsgroup    *gp;
  23089. Rstruc newsarticle  *ap;
  23090. {
  23091.  struct texthdr    *texthdrp;
  23092.  char               title     [81];
  23093.  
  23094.  /* If article is not specified, use main nncb, else article's text */
  23095.  
  23096.  texthdrp = (ap ? &ap->thdr : &np->thdr);
  23097.  
  23098.  if (np->batch_mode) {
  23099.    NNMbtext(np,texthdrp,NULL);
  23100.    return;
  23101.  }
  23102.  
  23103.  if (ap) sprintf(title, "%s:%d ",        gp->name, ap->number);
  23104.  else    sprintf(title, "NewsServer:%s ",np->nnserver);
  23105.  
  23106.  NNMview(np,gp,ap,texthdrp,title);
  23107.  return; 
  23108. }
  23109.  
  23110. ./   ADD NAME=NNMXARTT,SSI=01090002
  23111.  
  23112.  /********************************************************************/
  23113.  /*                                                                  */
  23114.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  23115.  /*                                                                  */
  23116.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  23117.  /*                                                                  */
  23118.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  23119.  /* including the implied warranties of merchantability and fitness, */
  23120.  /* are expressly denied.                                            */
  23121.  /*                                                                  */
  23122.  /* Provided this copyright notice is included, this software may    */
  23123.  /* be freely distributed and not offered for sale.                  */
  23124.  /*                                                                  */
  23125.  /* Changes or modifications may be made and used only by the maker  */
  23126.  /* of same, and not further distributed.  Such modifications should */
  23127.  /* be mailed to the author for consideration for addition to the    */
  23128.  /* software and incorporation in subsequent releases.               */
  23129.  /*                                                                  */
  23130.  /********************************************************************/
  23131.  
  23132. #pragma  csect(code,  "NN@XARTT")
  23133. #pragma  csect(static,"NN$XARTT")
  23134. #include "nn.h"
  23135.  
  23136. #define FORCE_DISPLAY_TO_TOP_AFTER_EXTRACT
  23137.  
  23138. /****** Emit an article title. ***************************************/
  23139.  
  23140. static Bool
  23141. emit_title(np,vp,xfp)
  23142. Rstruc nncb         *np;
  23143. VARK                *vp;
  23144. FILE                *xfp;
  23145. {
  23146.  Rstruc newsarticle *ap = VARK2PARTICLE(*vp);
  23147.  char               *stat;
  23148.  
  23149.  if      IsMissing(*vp)  stat = "Missing";
  23150.  else if IsUnread(*vp)   stat = "Unread";
  23151.  else if IsRead(*vp)     stat = "Read";
  23152.  else                    stat = "?";
  23153.  
  23154.  if (np->article_rows == 1) {
  23155.    fprintf(xfp,"%7d %-51.51s %-8.8s %11.11s\n",
  23156.                 ap->number, ap->subject, stat, ap->date);
  23157.  }
  23158.  else {
  23159.    fprintf(xfp,"%7d %-51.51s %-8.8s\n",
  23160.                ap->number, ap->subject, stat);
  23161.  }
  23162.  if (np->article_rows >= 2) {
  23163.    fprintf(xfp,"        %-51.51s %11.11s\n", ap->from, ap->date);
  23164.  }
  23165.  if (np->article_rows >= 3) {
  23166.    fprintf(xfp,"        %-51.51s\n", ap->message_id);
  23167.  }
  23168.  if (ferror(xfp)) return FALSE;
  23169.  else return TRUE;
  23170. }
  23171.  
  23172. /****** Extract article titles. **************************************/
  23173.  
  23174. Bool
  23175. NNMxartt(np,gp,mode)
  23176. Rstruc nncb         *np;
  23177. Rstruc newsgroup    *gp;
  23178. enum data_set_type   mode;
  23179. {
  23180.  FILE               *xfp;
  23181.  int                 count;
  23182.  VARK               *vp;
  23183.  VARK               *vpfirst;
  23184.  VARK               *vplast;
  23185.  VARK              **wp;
  23186.  VARK              **wpfirst;
  23187.  VARK              **wplast;
  23188.  struct extraction  *ep;
  23189.  struct extraction   the_extraction;
  23190.  
  23191.  if (!gp->article_vector) {
  23192.    ERR2("Newsgroup %s contains no articles.",gp->name);
  23193.    return FALSE;
  23194.  }
  23195.  
  23196.  /* Display panel asking for data set name into which to extract. */
  23197.  
  23198.  ep = &the_extraction;
  23199.  memset(ep,0,sizeof(struct extraction));
  23200.  ep->mode = mode;
  23201.  if (ep->mode == JES)
  23202.       strcpy(ep->panelname,"NNMPPRN1");
  23203.  else strcpy(ep->panelname,"NNMPEXN1");
  23204.  
  23205.  if (!((xfp=NNMgetds(np,ep)))) return TRUE;
  23206.  
  23207.  /* If append mode, and a separator line was specified, use it. */
  23208.  
  23209.  if (ep->appending && *ep->separator) {
  23210.    fprintf(xfp,"%s\n",ep->separator);
  23211.    if (ep->blanking) fprintf(xfp,"\n");
  23212.  }
  23213.  
  23214.  fprintf(xfp," Newsgroup: %-43.43s     Status   Date\n\n", gp->name);
  23215.  
  23216.  count = NNMrart(np,gp,FALSE,FALSE);  /* Retrieve article titles */
  23217.  
  23218.  if (gp->sort_vector) {
  23219.    wpfirst = gp->sort_vector;
  23220.    wplast  = gp->sort_vector + gp->sort_count - 1;
  23221.    for (wp = wpfirst; wp <= wplast; wp++) {
  23222.      if (IsEligible(**wp)) {
  23223.        if (!emit_title(np,*wp,xfp)) break;
  23224.      }
  23225.    }
  23226. #ifdef FORCE_DISPLAY_TO_TOP_AFTER_EXTRACT
  23227.    np->top_sorted_article = gp->sort_vector;
  23228. #endif
  23229.  }
  23230.  else {
  23231.    vpfirst = &GETVARKFIRST(gp);
  23232.    vplast  = &GETVARKLAST(gp);
  23233.    for (vp = vpfirst; vp <= vplast; vp++) {
  23234.      if (IsEligible(*vp)) {
  23235.        if (!emit_title(np,vp,xfp)) break;
  23236.      }
  23237.    }
  23238. #ifdef FORCE_DISPLAY_TO_TOP_AFTER_EXTRACT
  23239.    np->top_article = gp->vector_first;
  23240. #endif
  23241.  }
  23242.  
  23243.  fprintf(xfp,"\n");
  23244.  
  23245.  if (ferror(xfp)) {
  23246.    ERR2("An output error occurred writing to %s.", ep->dsname);
  23247.  }
  23248.  else {
  23249.    WARN2("A list of titles has been written to %s.", ep->dsname);
  23250.  }
  23251.  
  23252.  (ep->closer)(np,ep,xfp,TRUE);   /* Close the file */
  23253.  
  23254.  return TRUE;
  23255. }
  23256.  
  23257. ./   ADD NAME=NNMXARTX,SSI=01120005
  23258.  
  23259.  /********************************************************************/
  23260.  /*                                                                  */
  23261.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  23262.  /*                                                                  */
  23263.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  23264.  /*                                                                  */
  23265.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  23266.  /* including the implied warranties of merchantability and fitness, */
  23267.  /* are expressly denied.                                            */
  23268.  /*                                                                  */
  23269.  /* Provided this copyright notice is included, this software may    */
  23270.  /* be freely distributed and not offered for sale.                  */
  23271.  /*                                                                  */
  23272.  /* Changes or modifications may be made and used only by the maker  */
  23273.  /* of same, and not further distributed.  Such modifications should */
  23274.  /* be mailed to the author for consideration for addition to the    */
  23275.  /* software and incorporation in subsequent releases.               */
  23276.  /*                                                                  */
  23277.  /********************************************************************/
  23278.  
  23279. #pragma  csect(code,  "NN@XARTX")
  23280. #pragma  csect(static,"NN$XARTX")
  23281. #include "nn.h"
  23282.  
  23283. /****** Extract an article. ******************************************/
  23284.  
  23285. static Bool
  23286. extract_it(np,gp,ep,vp,xfpp,newtopp)
  23287. Rstruc nncb         *np;
  23288. Rstruc newsgroup    *gp;
  23289. struct extraction   *ep;
  23290. VARK                *vp;
  23291. FILE               **xfpp;
  23292. int                 *newtopp;
  23293. {
  23294.  struct newsarticle *ap;
  23295.  char               *cp1;
  23296.  char               *cp2;
  23297.  int                 anum;
  23298.  char                pdspec [32];
  23299.  
  23300.  if (np->extract_write_error || np->extract_close_error) return FALSE;
  23301.  anum = VARK2NUMBER(gp,vp);
  23302.  if (anum > ep->to_article_number)                       return FALSE;
  23303.  if (anum < ep->from_article_number)                     return TRUE;
  23304.  if (!(NNMcar(np,gp,anum,vp,&ap,NULL,RETRIEVE)))         return TRUE;
  23305.  
  23306.  if (ep->mode == PDS) {
  23307.    sprintf(ep->member,"%8.8d",anum);
  23308.    for (cp1 = ep->member, cp2 = ep->member_prefix;
  23309.         *cp1 == '0' && *cp2;
  23310.         cp1++, cp2++) {
  23311.      *cp1 = *cp2;
  23312.    }
  23313.    (void)NNMivput(np,"NNEXMEM ",ep->member,-1);
  23314.    sprintf(pdspec,"dd:%s(%s)",ep->ddname,ep->member);
  23315.  }
  23316.  else {
  23317.    (void)NNMivput(np,"NNEXMEM "," ",-1);
  23318.  }
  23319.  
  23320.  if (*newtopp == 0) *newtopp = anum;
  23321.  
  23322.  if (!NNMpick(np,ap)) {       /* Pick article to process */
  23323.    fprintf(stderr,"\n*** Error accessing article %d\n",ap->number);
  23324.    return TRUE;
  23325.  }
  23326.  
  23327.  if (ep->mode == PDS) {
  23328.    (*xfpp) = OPEN_TEXT_FILE_FOR_WRITE(pdspec);
  23329.    if (!(*xfpp)) {
  23330.      perror(pdspec);
  23331.      ERR3("Cannot open member %s of PDS %s.", ep->member, ep->dsname);
  23332.      return FALSE;
  23333.    }
  23334.  }
  23335.  
  23336.  np->extract_file = (*xfpp);
  23337.  np->extractionp  = ep;
  23338.  
  23339.  NNMdoit(np,ap, ep->mode==JES ? 'P' : 'E'); /* Process article picked*/
  23340.  
  23341.  if (np->extract_write_error || np->extract_close_error) {
  23342.    /*
  23343.     * if (ep->mode == PDS) {
  23344.     *   if (fclose((*xfpp)) < 0) {
  23345.     *     /* perror(ep->dsname); */
  23346.    /*   ERR2("An error occurred closing data set %s.", ep->dsname);
  23347.     *     np->extract_close_error = TRUE;
  23348.     *   }
  23349.     * }
  23350.     */
  23351.    *newtopp = ap->number;
  23352.    return FALSE;
  23353.  }
  23354.  
  23355.  /* If not appending (always true for PDS), close was done in NNMxtx.*/
  23356.  
  23357.  if (ep->mode == SEQ) {
  23358.    if (!ep->appending) {
  23359.      (ep->closer)(np,ep,*xfpp,FALSE);   /* Close the file */
  23360.      if (np->extract_close_error) {
  23361.        *newtopp = ap->number;
  23362.        return FALSE;
  23363.      }
  23364.      (*xfpp) = OPEN_TEXT_FILE_FOR_APPEND(ep->dsname);
  23365.      if (!(*xfpp)) {
  23366.        perror(ep->dsname);
  23367.        ERR2("Unable to open file %s.", ep->dsname);
  23368.        np->extract_write_error = TRUE;
  23369.        *newtopp = ap->number;
  23370.        return FALSE;
  23371.      }
  23372.      ep->appending = TRUE;
  23373.    }
  23374.  }
  23375.  return TRUE;
  23376.  
  23377. }
  23378.  
  23379. /****** Extract article text. ****************************************/
  23380.  
  23381. Bool
  23382. NNMxartx(np,gp,mode)
  23383. Rstruc nncb         *np;
  23384. Rstruc newsgroup    *gp;
  23385. enum data_set_type   mode;
  23386. {
  23387.  Rstruc newsarticle *ap;
  23388.  FILE               *xfp;
  23389.  struct extraction  *ep;
  23390.  VARK               *vp;
  23391.  VARK               *vpfirst;
  23392.  VARK               *vplast;
  23393.  VARK              **wp;
  23394.  VARK              **wpfirst;
  23395.  VARK              **wplast;
  23396.  int                 new_top_article = 0;
  23397.  struct extraction   the_extraction;
  23398.  
  23399.  if (!gp->article_vector) {
  23400.    ERR2("Newsgroup %s contains no articles.",gp->name);
  23401.    return FALSE;
  23402.  }
  23403.  
  23404.  /* Display panel asking for data set name into which to extract. */
  23405.  
  23406.  ep = &the_extraction;
  23407.  memset(ep,0,sizeof(struct extraction));
  23408.  ep->mode = mode;
  23409.  ep->article_count = gp->article_count;
  23410.  switch (ep->mode) {
  23411.    case PDS: strcpy(ep->panelname,"NNMPEXNP"); break;
  23412.    case JES: strcpy(ep->panelname,"NNMPPRNS"); break;
  23413.    case SEQ: strcpy(ep->panelname,"NNMPEXNS"); break;
  23414.  }
  23415.  
  23416.  if (!((xfp=NNMgetds(np,ep)))) return TRUE;
  23417.  
  23418.  np->extract_tab_expanding          = ep->tab_expanding;
  23419.  np->extract_appending              = ep->mode == PDS ? FALSE : TRUE;
  23420.  np->extract_ejecting               = ep->ejecting;
  23421.  np->extract_blank_before_separator = ep->blanking;
  23422.  np->extract_separator_line         = ep->separator;
  23423.  np->extract_write_error            = FALSE;
  23424.  np->extract_close_error            = FALSE;
  23425.  
  23426.  /* for each article (subject to range option), write */
  23427.  
  23428.  if (gp->sort_vector) {
  23429.    wpfirst = gp->sort_vector;
  23430.    wplast  = gp->sort_vector + gp->sort_count - 1;
  23431.    for (wp = wpfirst; wp <= wplast; wp++) {
  23432.      if (!extract_it(np,gp,ep,*wp,&xfp,&new_top_article)) break;
  23433.    }
  23434.  }
  23435.  else {
  23436.    vpfirst = &GETVARKFIRST(gp);
  23437.    vplast  = &GETVARKLAST(gp);
  23438.    for (vp = vpfirst; vp <= vplast; vp++) {
  23439.      if (!extract_it(np,gp,ep,vp,&xfp,&new_top_article)) break;
  23440.    }
  23441.  }
  23442.  
  23443.  if (np->extract_write_error || np->extract_close_error)
  23444.     np->top_article = new_top_article;
  23445.  else if (new_top_article)
  23446.     np->top_article = new_top_article;
  23447.  
  23448.  if (xfp) {
  23449.    if      (np->extract_write_error) {
  23450.      ERR2("An error occurred writing to %s.", ep->dsname);
  23451.    }
  23452.    else if (np->extract_close_error) {
  23453.      if (ep->mode == PDS) {
  23454.      ERR3("Cannot store member %s in %s.  Check directory space.",
  23455.           ep->member, ep->dsname);
  23456.      }
  23457.      else ERR2("An error occurred closing %s.", ep->dsname);
  23458.    }
  23459.    else {
  23460.      WARN3("Articles from %s have been written to %s.",
  23461.            gp->name, ep->dsname);
  23462.    }
  23463.  }
  23464.  
  23465.  (ep->closer)(np,ep,xfp,TRUE);   /* "Close" the PDS or the file */
  23466.  
  23467.  return TRUE;
  23468. }
  23469.  
  23470. ./   ADD NAME=NNMXLIST,SSI=01050026
  23471.  
  23472.  /********************************************************************/
  23473.  /*                                                                  */
  23474.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  23475.  /*                                                                  */
  23476.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  23477.  /* including the implied warranties of merchantability and fitness, */
  23478.  /* are expressly denied.                                            */
  23479.  /*                                                                  */
  23480.  /* Provided this copyright notice is included, this software may    */
  23481.  /* be freely distributed and not offered for sale.                  */
  23482.  /*                                                                  */
  23483.  /* Changes or modifications may be made and used only by the maker  */
  23484.  /* of same, and not further distributed.  Such modifications should */
  23485.  /* be mailed to the author for consideration for addition to the    */
  23486.  /* software and incorporation in subsequent releases.               */
  23487.  /*                                                                  */
  23488.  /********************************************************************/
  23489.  
  23490. #pragma  csect(code,  "NN@XLIST")
  23491. #pragma  csect(static,"NN$XLIST")
  23492. #include "nn.h"
  23493.  
  23494. /****** Extract newsgroup listing. ***********************************/
  23495.  
  23496. static void
  23497. output_newsgroup_line(np,gp,xfp)
  23498. Rstruc nncb         *np;
  23499. Rstruc newsgroup    *gp;
  23500. FILE                *xfp;
  23501. {
  23502.  char                temp   [81];
  23503.  
  23504.  if (gp->article_count == 0) strcpy(temp,"");
  23505.  else sprintf(temp,"%7d - %7d", gp->low_number, gp->high_number);
  23506.  
  23507.  fprintf(xfp,"%*.*s %*.*s %c %7d %7d %s\n",
  23508.          strlen(gp->name),
  23509.          39,
  23510.          gp->name,
  23511.          39-strlen(gp->name),
  23512.          39-strlen(gp->name),
  23513.          ".........................................",
  23514.          (gp->registered ? 'R' : ' '),
  23515.          gp->unread_count,
  23516.          gp->article_count,
  23517.          temp);
  23518.  
  23519.  return; 
  23520.  
  23521. }
  23522.  
  23523. /****** Extract newsgroup listing. ***********************************/
  23524.  
  23525. Bool
  23526. NNMxlist(np,mode)
  23527. Rstruc nncb         *np;
  23528. enum data_set_type   mode;
  23529. {
  23530.  Rstruc newsgroup   *gp;
  23531.  FILE               *xfp;
  23532.  struct extraction  *ep;
  23533.  char                temp   [72];
  23534.  struct extraction   the_extraction;
  23535.  
  23536.  /* Display panel asking for data set name into which to extract. */
  23537.  
  23538.  ep = &the_extraction;
  23539.  memset(ep,0,sizeof(struct extraction));
  23540.  ep->mode = mode;
  23541.  if (ep->mode == JES)
  23542.       strcpy(ep->panelname, "NNMPPRNG");
  23543.  else strcpy(ep->panelname, "NNMPEXNG");
  23544.  
  23545.  if (!((xfp=NNMgetds(np,ep)))) return TRUE;
  23546.  
  23547.  /* If append mode, and a separator line was specified, use it. */
  23548.  
  23549.  if (ep->appending && *ep->separator) {
  23550.    fprintf(xfp,"%s\n",ep->separator);
  23551.    if (ep->blanking) fprintf(xfp,"\n");
  23552.  }
  23553.  
  23554.  fprintf(xfp,"\
  23555.   Newsgroup Listing                          Unread   Count      \
  23556.   Range\n\n");
  23557.  
  23558.  switch (np->newsgroup_order) {
  23559.    case NNTP_LIST_ORDER:
  23560.         for (gp = np->first_newsgroup_alt; gp; gp = gp->next2) {
  23561.           if (GroupInTable(gp)) {
  23562.             output_newsgroup_line(np,gp,xfp);
  23563.           }
  23564.         }
  23565.         break;
  23566.  
  23567.    case NEWSRC_ORDER:        /* not implemented - fall through */
  23568.    case ALPHABETICAL_ORDER:
  23569.    default:                  /* default is alphabetical order */
  23570.         for (gp = np->first_newsgroup; gp; gp = gp->next) {
  23571.           if (GroupInTable(gp)) {
  23572.             output_newsgroup_line(np,gp,xfp);
  23573.           }
  23574.         }
  23575.         break;
  23576.  }
  23577.  
  23578.  fprintf(xfp,"\n");
  23579.  
  23580.  if (ferror(xfp)){
  23581.    ERR2("An error occurred writing to %s.", ep->dsname);
  23582.  }
  23583.  else {
  23584.    WARN2("A list of titles has been written to %s.", ep->dsname);
  23585.  }
  23586.  
  23587.  (ep->closer)(np,ep,xfp,TRUE);     /* Close the file */
  23588.  
  23589.  return TRUE;
  23590.  
  23591. }
  23592.  
  23593. ./   ADD NAME=NNMXTX,SSI=010E0043
  23594.  
  23595.  /********************************************************************/
  23596.  /*                                                                  */
  23597.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  23598.  /*                                                                  */
  23599.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  23600.  /* including the implied warranties of merchantability and fitness, */
  23601.  /* are expressly denied.                                            */
  23602.  /*                                                                  */
  23603.  /* Provided this copyright notice is included, this software may    */
  23604.  /* be freely distributed and not offered for sale.                  */
  23605.  /*                                                                  */
  23606.  /* Changes or modifications may be made and used only by the maker  */
  23607.  /* of same, and not further distributed.  Such modifications should */
  23608.  /* be mailed to the author for consideration for addition to the    */
  23609.  /* software and incorporation in subsequent releases.               */
  23610.  /*                                                                  */
  23611.  /********************************************************************/
  23612.  
  23613. #pragma  csect(code,  "NN@XTX  ")
  23614. #pragma  csect(static,"NN$XTX  ")
  23615. #include "nn.h"
  23616.  
  23617. #define XFPUTC(A)     np->extract_write_error = (fputc((A),xfp) == EOF)
  23618.  
  23619. #define XFWRITE(A,B)  fwrite((A),(B),1,xfp), \
  23620.                       np->extract_write_error = (ferror(xfp) != 0)
  23621.  
  23622. /****** Extract the lines of server text into a data set. ************/
  23623.  
  23624. Bool
  23625. NNMxtx(np,ap,headerstoo)
  23626. Rstruc nncb         *np;
  23627. Rstruc newsarticle  *ap;
  23628. Fool                 headerstoo;
  23629. {
  23630.  FILE               *xfp;
  23631.  struct texthdr     *thp;
  23632.  struct textline    *tp;
  23633.  struct extraction  *ep;
  23634.  int                 l;
  23635.  int                 linelen;
  23636.  char               *cp;
  23637.  Bool                printing;
  23638.  char                formatted_number [11];
  23639.  struct extraction   the_extraction;
  23640.  
  23641.  /* If article is not specified, use main nncb, else article's text */
  23642.  
  23643.  thp = (ap ? &ap->thdr : &np->thdr);
  23644.  
  23645.  printing = np->printing;
  23646.  np->printing = FALSE;
  23647.  
  23648.  /* Set article data for message. */
  23649.  
  23650.  if (ap) {
  23651.    sprintf(formatted_number,"%d",ap->number);
  23652.    (void)NNMivput(np,"NNTNUM ",  formatted_number, -1);
  23653.    (void)NNMivput(np,"NNTSUBJ ", ap->subject,      -1);
  23654.  }
  23655.  else {
  23656.    (void)NNMivput(np,"NNTNUM ",  "", -1);
  23657.    (void)NNMivput(np,"NNTSUBJ ", "", -1);
  23658.  }
  23659.  
  23660.  if (np->extract_file) {
  23661.    if (!np->following_up) {
  23662.      (void)NNMispf(np,"CONTROL DISPLAY LOCK");
  23663.      if (printing)
  23664.         (void)NNMispf(np,"DISPLAY PANEL(NNMLPRN2)");
  23665.      else
  23666.         (void)NNMispf(np,"DISPLAY PANEL(NNMLEXN2)");
  23667.    }
  23668.    xfp = np->extract_file;
  23669.    ep = np->extractionp;
  23670.  }
  23671.  else {
  23672.  
  23673.    ep = &the_extraction;
  23674.    memset(ep,0,sizeof(struct extraction));
  23675.    if (printing) {
  23676.      ep->mode = JES;
  23677.      strcpy(ep->panelname,"NNMPPRDS");
  23678.    }
  23679.    else {
  23680.      ep->mode = SEQ;
  23681.      strcpy(ep->panelname,"NNMPEXDS");
  23682.    }
  23683.  
  23684.    if (!((xfp=NNMgetds(np,ep)))) return FALSE;
  23685.  
  23686.    np->extract_tab_expanding          = ep->tab_expanding;
  23687.    np->extract_appending              = ep->appending;
  23688.    np->extract_ejecting               = ep->ejecting;
  23689.    np->extract_blank_before_separator = ep->blanking;
  23690.    np->extract_separator_line         = ep->separator;
  23691.  }
  23692.  
  23693.  /* If append mode, and a separator line was specified, use it. */
  23694.  
  23695.  np->extract_write_error = FALSE;
  23696.  np->extract_close_error = FALSE;
  23697.  
  23698.  if (np->extract_ejecting) {
  23699.    XFPUTC('\f');
  23700.  }
  23701.  
  23702.  if (np->extract_appending) {
  23703.    XFPUTC('\n');
  23704.    if (np->extract_separator_line && *np->extract_separator_line) {
  23705.      XFWRITE(np->extract_separator_line,
  23706.              strlen(np->extract_separator_line));
  23707.      XFPUTC('\n');
  23708.      if (np->extract_blank_before_separator) XFPUTC('\n');
  23709.    }
  23710.  }
  23711.  
  23712.  if      (headerstoo)               tp = thp->first_text_line;
  23713.  else if ((tp=thp->text_body_line)) tp = tp->next;
  23714.  
  23715.  linelen = (printing ? 120 : 251);
  23716.  
  23717.  for (; tp && !np->extract_write_error; tp = tp->next) {
  23718.    if (tp->text_length == 0) {
  23719.      if (np->following_up) XFPUTC('>');
  23720.      XFPUTC('\n');
  23721.    }
  23722.    else if (tp->text_length > 0) {
  23723.      if (np->extract_tab_expanding) {
  23724.        cp = tp->tab_expanded_text;
  23725.        l  = tp->tab_expanded_text_length;
  23726.      }
  23727.      else {
  23728.        cp = tp->text;
  23729.        l  = tp->text_length;
  23730.      }
  23731.      for (; l>0 && !np->extract_write_error; cp+=linelen, l-=linelen) {
  23732.        if (np->following_up) XFPUTC('>');
  23733.        XFWRITE(cp,(l > linelen ? linelen : l));
  23734.        XFPUTC('\n');
  23735.      }
  23736.    }
  23737.  }
  23738.  
  23739.  if (!np->extract_write_error && ferror(xfp))
  23740.     np->extract_write_error = TRUE;
  23741.  
  23742.  if (!np->following_up) {
  23743.    if (!np->extract_appending || !np->extract_file) {
  23744.      (ep->closer)(np,ep,xfp,printing);   /* Close the file */
  23745.      if (np->extract_close_error) return FALSE;
  23746.    }
  23747.  }
  23748.  if (!np->extract_file) {
  23749.    if (np->extract_write_error) {
  23750.      ERR2("An error occurred writing to %s.",ep->dsname);
  23751.      np->extract_write_error = TRUE;
  23752.    }
  23753.    else if (ap) {
  23754.      WARN3("Article %d has been written to %s.",ap->number,ep->dsname);
  23755.    }
  23756.    else {
  23757.      WARN2("Displayed text has been written to %s.",ep->dsname);
  23758.    }
  23759.  }
  23760.  if (np->extract_write_error) return FALSE;
  23761.  else return TRUE;
  23762. }
  23763.  
  23764. ./ ENDUP 
  23765. ?!
  23766. //CLIST    EXEC NNLOAD,TRK1='4',TO='CLIST'
  23767. //SYSIN    DD DATA,DLM='?!'
  23768. ./   ADD NAME=NNMFIUCV,SSI=01010036
  23769. /* REXX.  This exec scans the job pack queues for IUCVMULT and returns
  23770.  * with an error code if IUCVMULT is already loaded under a
  23771.  * different TCB. This can only happen under PIE MultiTSO or a
  23772.  * similar product that makes multiple job step TCB's.
  23773.  */
  23774.  
  23775. trace off
  23776. signal on novalue
  23777.  
  23778. search_name = "IUCVMULT"
  23779. count = 0
  23780. foundtcb. = ""
  23781. current_tcb  = getword24("21C")
  23782. current_job_step_tcb = getword24(current_tcb,"7C")
  23783. current_ascb = getword24("224")
  23784. current_asxb = getword31(current_ascb,"6C")
  23785. first_tcb    = getword24(current_asxb,"4")
  23786. tcb = first_tcb
  23787. motherflag = 0
  23788. do forever
  23789.  if motherflag = 0 then do
  23790.   call process
  23791.   daughter_tcb = getword24(tcb,"88")
  23792.   if daughter_tcb \= "00000000" then do
  23793.    tcb = daughter_tcb
  23794.    iterate
  23795.   end
  23796.  end
  23797.  motherflag = 0
  23798.  sister_tcb = getword24(tcb, "80")
  23799.  if sister_tcb \= "00000000" then do
  23800.   tcb = sister_tcb
  23801.   iterate
  23802.  end
  23803.  mother_tcb = getword24(tcb, "84")
  23804.  if mother_tcb \= "00000000" then do
  23805.   tcb = mother_tcb
  23806.   motherflag = 1
  23807.   iterate
  23808.  end
  23809.  leave
  23810. end
  23811.  
  23812. if count = 0 then return 0
  23813. problem = 0
  23814. do i = 1 to count
  23815.  if foundtcb.i = current_job_step_tcb then do
  23816.   /*
  23817.   say search_name "is already loaded under current TCB at "foundtcb.i"."
  23818.   */
  23819.  end
  23820.  else do 
  23821.   /*
  23822.   say search_name "is loaded under different TCB at "foundtcb.i"."
  23823.   */
  23824.   problem = 1
  23825.  end
  23826. end
  23827.  
  23828. if problem = 1 then return 1
  23829.  
  23830. else return 0
  23831.  
  23832. process: 
  23833.  
  23834.  jpq = getword31(tcb,"2C")
  23835.  cde = jpq
  23836.  do while cde \= "00000000"
  23837.   cde_contents = storage(cde,32)
  23838.   cde_name = substr(cde_contents,9,8)
  23839.   cde_epa  = substr(cde_contents,9,8)
  23840.   if search_name = cde_name then do
  23841.    count = count + 1
  23842.    foundtcb.count = tcb
  23843.   end
  23844.   cde = getword31(cde,"0")
  23845.  end
  23846.  
  23847. return
  23848.  
  23849. getword31: parse arg addr, offset
  23850. temp1 = x2d(addr)
  23851. if offset = "" then temp2 = 0
  23852. else temp2 = x2d(offset)
  23853. return c2x(storage(d2x(temp1+temp2),4))
  23854.  
  23855. getword24: parse arg addr, offset
  23856. temp1 = x2d(addr)
  23857. if offset = "" then temp2 = 0
  23858. else temp2 = x2d(offset)
  23859. return "00"c2x(storage(d2x(temp1+temp2+1),3))
  23860.  
  23861. ./   ADD NAME=NNMMAIL,SSI=01030000
  23862. /* REXX */
  23863.  
  23864. /*********************************************************************/
  23865. /*                                                                   */
  23866. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     */
  23867. /*                                                                   */
  23868. /* This software is provided on an "AS IS" basis.  All warranties,   */
  23869. /* including the implied warranties of merchantability and fitness,  */
  23870. /* are expressly denied.                                             */
  23871. /*                                                                   */
  23872. /* Provided this copyright notice is included, this software may     */
  23873. /* be freely distributed and not offered for sale.                   */
  23874. /*                                                                   */
  23875. /* Changes or modifications may be made and used only by the maker   */
  23876. /* of same, and not further distributed.  Such modifications should  */
  23877. /* be mailed to the author for consideration for addition to the     */
  23878. /* software and incorporation in subsequent releases.                */
  23879. /*                                                                   */
  23880. /*********************************************************************/
  23881.  
  23882. /**********************************************************************/
  23883. /*                                                                    */
  23884. /* Argument 1: mail data set                                          */
  23885. /* Argument 2: recipient(s)                                           */
  23886. /*                                                                    */
  23887. /**********************************************************************/
  23888.  
  23889. trace off
  23890. address TSO
  23891.  
  23892. /* Tailor these to your installation requirements. */
  23893.  
  23894. local_userid    = userid()
  23895. local_domain    = "MVS"
  23896. local_origin    = "mvs.draper.com"
  23897. local_smtp_node = "SMTPSRV"
  23898.  
  23899. parse arg maildsn to
  23900.  
  23901. if pos("@",to) = 0 then to = to"@"local_origin
  23902. else do
  23903.  parse var to before "<" after ">" junk
  23904.  if after <> "" then to = after
  23905. end
  23906.  
  23907. "ALLOC FI(NNMMAILI) SHR REU DA("maildsn")"
  23908. if rc \= 0 then return rc
  23909. "EXECIO * DISKR NNMMAILI (FINIS STEM IN.)"
  23910. if rc \= 0 then return rc
  23911. "newstack"
  23912. say   "HELO" local_domain
  23913. queue "HELO" local_domain
  23914. say   "MAIL FROM:<"local_userid"@"local_origin">"
  23915. queue "MAIL FROM:<"local_userid"@"local_origin">"
  23916. say   "RCPT TO:<"to">"
  23917. queue "RCPT TO:<"to">"
  23918. queue "DATA"
  23919. do i = 1 to in.0
  23920.  if left(in.i,1) = "." then queue "."in.i
  23921.  else if in.i = "" then queue " "
  23922.  else queue in.i
  23923. end
  23924. queue "."
  23925. queue "QUIT"
  23926. queue "" 
  23927. "EXECIO * DISKW NNMMAILI (FINIS)"
  23928. if rc \= 0 then return rc
  23929. "delstack"
  23930. "FREE FI(NNMMAILI)"
  23931.  
  23932. "TRANSMIT" local_domain"."local_smtp_node,
  23933.            "DATASET("maildsn") NOEPILOG NOLOG NOPROLOG"
  23934.  
  23935. return 0 
  23936.  
  23937. /* The following function enquotes a string. */
  23938. quote:
  23939. parse arg string
  23940. ix = 1
  23941. do forever
  23942.  ix = pos("'",string,ix)
  23943.  if ix = 0 then return "'"string"'"
  23944.  string = insert("'",string,ix)
  23945.  ix=ix+2 
  23946. end
  23947. ./   ADD NAME=NNMVS,SSI=010D0000
  23948. /* REXX. Syntax:  NNMVS  (we'll do the rest)   */
  23949.  
  23950. /*********************************************************************/
  23951. /*                                                                   */
  23952. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     */
  23953. /*                                                                   */
  23954. /* This software is provided on an "AS IS" basis.  All warranties,   */
  23955. /* including the implied warranties of merchantability and fitness,  */
  23956. /* are expressly denied.                                             */
  23957. /*                                                                   */
  23958. /* Provided this copyright notice is included, this software may     */
  23959. /* be freely distributed and not offered for sale.                   */
  23960. /*                                                                   */
  23961. /* Changes or modifications may be made and used only by the maker   */
  23962. /* of same, and not further distributed.  Such modifications should  */
  23963. /* be mailed to the author for consideration for addition to the     */
  23964. /* software and incorporation in subsequent releases.                */
  23965. /*                                                                   */
  23966. /*********************************************************************/
  23967.  
  23968. /* *** Customize the following lines for your installation. *** */
  23969. /*                                                              */
  23970. /* Note:  If you wish to specify a different ISPF APPLID for    */
  23971. /* NNMVS, you will have to use the SELECT service to invoke     */
  23972. /* the load module.  If so, uncomment the LIBDEF's for ISPLLIB  */
  23973. /* and the SELECT call, and comment out the TSO CALL call.      */
  23974. /*                                                              */
  23975. /* Note:  If you choose a panel library that is in TSO users'   */
  23976. /* default ISPF allocations, you can remove the LIBDEF call.    */
  23977. /*                                                              */
  23978.  
  23979. nnmprefix      = "NNMVS"
  23980. nnmpanelsuffix = "ISPPLIB"
  23981. nnmloadsuffix  = "LOAD"
  23982. nnmlmod        = "NNMMAIN"
  23983. nnmpanel       = nnmprefix"."nnmpanelsuffix
  23984. nnmload        = nnmprefix"."nnmloadsuffix
  23985. nnmappl        = "ISR"
  23986.  
  23987. trace off
  23988. signal on novalue
  23989. libdeffed = 0
  23990. parse arg args
  23991. "ISPQRY" 
  23992. if rc > 0 then do
  23993.  parse source . . execname . execds .
  23994.  if execds = "?" then
  23995.   icmd = "%"execname args
  23996.  else
  23997.   icmd = "EX '"execds"("execname")'" quote(args)
  23998.  call startispf "NEWAPPL("nnmappl") CMD("icmd")"
  23999.  exit
  24000. end
  24001. signal on failure
  24002. signal on halt
  24003. testparm = "-"
  24004. if wordpos("TEST", translate(args)) > 0 then testparm = testparm || "t"
  24005. else ,
  24006. if wordpos("DEBUG",translate(args)) > 0 then testparm = testparm || "d"
  24007. else testparm = ""
  24008.  
  24009. if find_iucvmult() <> 0 then do
  24010.  say,
  24011. "A TCP/IP socket application may be active elsewhere in your session."
  24012.  say "Please terminate the other application before trying this one."
  24013.  exit
  24014. end
  24015.  
  24016. call libdef
  24017. call nnm_dialog
  24018.  
  24019. cleanup: 
  24020. if libdeffed then call unlibdef
  24021. exit
  24022. error:failure:halt:say "NNMVS: Severe lossage."
  24023. say "Statement:" sourceline(sigl)
  24024. exit
  24025.  
  24026. nnm_dialog:
  24027.  
  24028. address TSO "CALL" "'"nnmload"("nnmlmod")'" quote(testparm)
  24029. /*
  24030.  * address ISPEXEC,
  24031.  *         "SELECT PGM("nnmlmod") PARM("quote(testparm)")",
  24032.  *         "NEWAPPL("nnmappl") PASSLIB"
  24033.  */
  24034. if rc \= 0 then say "Return code from" nnmlmod "program is" rc
  24035. return
  24036.  
  24037. libdef:
  24038. address ISPEXEC "LIBDEF ISPPLIB DATASET  ID('"nnmpanel"')"
  24039. /*
  24040.  * address ISPEXEC "LIBDEF ISPLLIB DATASET  ID('"nnmload"')"
  24041.  */
  24042. libdeffed = 1
  24043. return
  24044.  
  24045. unlibdef:
  24046. /*
  24047.  * address ISPEXEC "LIBDEF ISPLLIB DATASET"
  24048.  */
  24049. address ISPEXEC "LIBDEF ISPPLIB DATASET"
  24050. libdeffed = 0
  24051. return
  24052.  
  24053. /*
  24054.  * The following function starts ISPF from READY mode.
  24055.  * Beware:  splitting the screen starts up an identical copy of the
  24056.  *          application, which may not be desirable.
  24057.  */
  24058.  
  24059. startispf: parse arg string
  24060. "ISPSTART" string
  24061. return
  24062.  
  24063. /* The following function enquotes a string. */
  24064.  
  24065. quote: parse arg string
  24066. ix = 1
  24067. do forever
  24068.  ix = pos("'",string,ix)
  24069.  if ix = 0 then return "'"string"'"
  24070.  string = insert("'",string,ix)
  24071.  ix=ix+2 
  24072. end
  24073.  
  24074. find_iucvmult: procedure
  24075.  
  24076. call nnmfiucv
  24077.  
  24078. return result
  24079.  
  24080. ./   ADD NAME=NNMVSC,SSI=01030012
  24081. PROC 0 TEST DEBUG BATCH +
  24082.        SERVER() GROUP() NEWSRC() OPTION() REGISTERSTATUS()
  24083.  
  24084. /*********************************************************************/
  24085. /*                                                                   */
  24086. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     */
  24087. /*                                                                   */
  24088. /* This software is provided on an "AS IS" basis.  All warranties,   */
  24089. /* including the implied warranties of merchantability and fitness,  */
  24090. /* are expressly denied.                                             */
  24091. /*                                                                   */
  24092. /* Provided this copyright notice is included, this software may     */
  24093. /* be freely distributed and not offered for sale.                   */
  24094. /*                                                                   */
  24095. /* Changes or modifications may be made and used only by the maker   */
  24096. /* of same, and not further distributed.  Such modifications should  */
  24097. /* be mailed to the author for consideration for addition to the     */
  24098. /* software and incorporation in subsequent releases.                */
  24099. /*                                                                   */
  24100. /*********************************************************************/
  24101.  
  24102. /**********************************************************************/
  24103. /*                                                                    */
  24104. /* This is the CLIST version of the NNMVS driver.  You may wish to    */
  24105. /* use this in place of the REXX version if:                          */
  24106. /*                                                                    */
  24107. /* - you don't have REXX (huh???)                                     */
  24108. /* - you don't have XPROC (you can probably get it from the same      */
  24109. /*   place you got NNMVS)                                             */
  24110. /* - you are experiencing RACF/ACF2/other-security-system problems    */
  24111. /*   trying to define access to the NNTP authorization file with      */
  24112. /*   program pathing rules or the equivalent                          */
  24113. /*                                                                    */
  24114. /* The disadvantages are:                                             */
  24115. /*                                                                    */
  24116. /* - You can use the CLIST from READY mode only implicitly.  In other */
  24117. /*   words, a user won't be able to type EXEC 'library.clist(NNMVS)'  */
  24118. /*   from READY mode - it must be in SYSPROC and executed by name.    */
  24119. /*                                                                    */
  24120. /* - You don't get the check for multiple TCP/IP applications.        */
  24121. /*                                                                    */
  24122. /* Of course, even if you don't have XPROC, you may still want to use */
  24123. /* the REXX exec instead - you just have to take out the XPROC call   */
  24124. /* and forget about being able to pass parameters to the exec.  That  */
  24125. /* isn't such a great loss, since none of the params are required.    */
  24126. /*                                                                    */
  24127. /**********************************************************************/
  24128.  
  24129. /* *** Customize the following lines for your installation. *** */
  24130. /*                                                              */
  24131. /* Note:  If you wish to specify a different ISPF APPLID for    */
  24132. /* NNMVS, you will have to use the SELECT service to invoke     */
  24133. /* the load module.  If so, uncomment the LIBDEF's for ISPLLIB  */
  24134. /* and the SELECT call, and comment out the TSO CALL call.      */
  24135. /*                                                              */
  24136. /* Note:  If you choose a panel library that is in TSO users'   */
  24137. /* default ISPF allocations, you can remove the LIBDEF call.    */
  24138. /*                                                              */
  24139.  
  24140. SET NNMCLIST       = NNMVS     /* name of this CLIST */
  24141. SET NNMPREFIX      = NNMVS
  24142. SET NNMPANELSUFFIX = ISPPLIB
  24143. SET NNMLOADSUFFIX  = LOAD
  24144. SET NNMLMOD        = NNMMAIN
  24145. SET NNMPANEL       = &STR(&NNMPREFIX..&NNMPANELSUFFIX)
  24146. SET NNMLOAD        = &STR(&NNMPREFIX..&NNMLOADSUFFIX)
  24147. SET NNMAPPL        = ISR
  24148.  
  24149. CONTROL NOCAPS
  24150.  
  24151. SET STACKED = N
  24152. SET LIBDEFFED = N
  24153. ISPQRY
  24154. IF &LASTCC > 0 THEN DO
  24155.  SET ICMD = &NRSTR(&NNMCLIST &TEST &DEBUG &BATCH +
  24156.                    SERVER('&SERVER') GROUP('&GROUP') +
  24157.                    NEWSRC('&NEWSRC') OPTION('&OPTION') +
  24158.                    REGISTERSTATUS('®ISTERSTATUS'))
  24159.  ISPSTART NEWAPPL(&NNMAPPL) CMD(&NRSTR(&ICMD))
  24160.  EXIT
  24161. END
  24162.  
  24163. IF &NRSTR(&OPTION) ^= &STR() THEN DO
  24164.  IF &LENGTH(&NRSTR(&OPTION)) ^= 1 +
  24165.   | &SYSINDEX(&NRSTR(&OPTION),TDB) ^= 0 THEN DO
  24166.   WRITE NNMVS: Invalid option, &NRSTR(&OPTION).
  24167.   EXIT CODE(12)
  24168.  END
  24169.  IF &NRSTR(&SERVER) = &STR() THEN DO
  24170.   WRITE NNMVS: SERVER required when OPTION specified.
  24171.   EXIT CODE(12)
  24172.  END
  24173.  IF &NRSTR(&NEWSRC) = &STR() THEN DO
  24174.   WRITE NNMVS: NEWSRC required when OPTION specified.
  24175.   EXIT CODE(12)
  24176.  END
  24177.  IF &NRSTR(&OPTION) = G && &NRSTR(&GROUP) = &STR() THEN DO
  24178.   WRITE NNMVS: GROUP required when OPTION(G) specified.
  24179.   EXIT CODE(12)
  24180.  END
  24181.  IF &NRSTR(REGISTERSTATUS) = &STR() THEN SET REGISTERSTATUS = PROMPT
  24182. END
  24183.  
  24184. SET TESTPARM = &STR(-)
  24185. IF &TEST  = TEST  THEN SET TESTPARM = &STR(&TESTPARM.t)
  24186. IF &DEBUG = DEBUG THEN SET TESTPARM = &STR(&TESTPARM.d)
  24187. IF &BATCH = BATCH THEN SET TESTPARM = &STR(&TESTPARM.b)
  24188.  
  24189. ISPEXEC LIBDEF ISPPLIB DATASET ID('&NNMPANEL')
  24190.  
  24191. /* ISPEXEC LIBDEF ISPLLIB DATASET ID('&NNMLOAD')
  24192.  
  24193. SET LIBDEFFED = Y
  24194.  
  24195. IF &NRSTR(&SERVER) NE THEN DO
  24196.  SET NNSERVER = &NRSTR(&SERVER)
  24197.  ISPEXEC VPUT (NNSERVER)
  24198. END
  24199.  
  24200. IF &NRSTR(&GROUP) NE THEN DO
  24201.  SET NNGROUPI = &NRSTR(&GROUP)
  24202.  ISPEXEC VPUT (NNGROUPI)
  24203. END
  24204.  
  24205. IF &NRSTR(&NEWSRC) NE THEN DO
  24206.  SET NNNEWSRF = &NRSTR(&NEWSRC)
  24207.  ISPEXEC VPUT (NNNEWSRF)
  24208. END
  24209.  
  24210. SET VPUTVARS =
  24211.  
  24212. IF &NRSTR(&SERVER) ^= &STR() THEN DO
  24213.  SET NNSERVER = &NRSTR(&SERVER)
  24214.  SET VPUTVARS = &STR(&VPUTVARS NNSERVER)
  24215. END
  24216.  
  24217. IF &NRSTR(&GROUP) ^= &STR() | &NRSTR(&OPTION) = G THEN DO
  24218.  SET NNGROUPI = &NRSTR(&GROUP)
  24219.  SET VPUTVARS = &STR(&VPUTVARS NNGROUPI)
  24220. END
  24221.  
  24222. IF &NRSTR(&NEWSRC) ^= &STR() THEN DO
  24223.  SET NNNEWSRF = &NRSTR(&NEWSRC)
  24224.  SET L = &LENGTH(&NRSTR(&NEWSRC))
  24225.  IF   &SUBSTR(1,&NEWSRC) = &STR(') +
  24226.    && &SUBSTR(&L,&NEWSRC) = &STR(') THEN DO
  24227.   SET NNNEWSRC = &SUBSTR(2:&L-1,&NRSTR(&NEWSRC))
  24228.  END
  24229.  ELSE SET NNNEWSRC = &NRSTR(&SYSPREF..&NEWSRC)
  24230.  SET VPUTVARS = &STR(&VPUTVARS NNNEWSRF NNNEWSRC)
  24231. END
  24232.  
  24233. IF &NRSTR(®ISTERSTATUS) ^= &STR() THEN DO
  24234.  SET NNREGNNG = &SUBSTR(1,&NRSTR(®ISTERSTATUS)
  24235.  SET VPUTVARS = &STR(&VPUTVARS NNREGNNG)
  24236. END
  24237.  
  24238. IF &STR(VPUTVARS) ^= &STR() THEN DO
  24239.  ISPEXEC VPUT (VPUTVARS) PROFILE
  24240. END
  24241.  
  24242. IF &NRSTR(&OPTION) ^= &STR() THEN DO
  24243.  SET TESTPARM = &NRSTR(&TESTPARM.&OPTION)
  24244. END
  24245.  
  24246. CALL '&NNMLOAD(&NNMLMOD)' '&NRSTR(&TESTPARM)'
  24247. /*
  24248. /* address ISPEXEC,
  24249. /* ISPEXEC SELECT PGM(&NNMLMOD) PARM('&NRSTR(&TESTPARM)') +
  24250. /*         NEWAPPL(&NNMAPPL) PASSLIB
  24251. /*
  24252. IF &LASTCC NE 0 THEN DO
  24253.  WRITE Return code from &NNMLMOD program is &LASTCC
  24254. END
  24255.  
  24256. IF &LIBDEFFED = Y THEN DO
  24257.  
  24258.  /* ISPEXEC LIBDEF ISPLLIB DATASET
  24259.  
  24260.  ISPEXEC LIBDEF ISPPLIB DATASET
  24261.  SET LIBDEFFED = N
  24262. END
  24263.  
  24264. EXIT
  24265.  
  24266. ./   ADD NAME=NNMVSL,SSI=01030003
  24267. /* REXX.  From Leonard D. Woren <ldw@mvsa.usc.edu>.
  24268.  *        Modified by SEB to remove MSGS file and other stuff...
  24269.  *
  24270.  */
  24271. trace off
  24272. signal on failure
  24273. signal on novalue
  24274.  
  24275. "XPROC 0 DEBUG LIST NEW OLD"
  24276. if rc <> 0 then return rc
  24277.  
  24278. If debug = 'DEBUG' Then Trace I
  24279. If list  = 'LIST'  Then Trace C
  24280. Address ISPEXEC
  24281.  
  24282. nnmvs_command = "%NNMVSP" new old
  24283. panel_name    = "NNL"
  24284. prof = "ISPPROF"
  24285. Address TSO "PIECHECK"
  24286. piecc = Rc
  24287. Select
  24288.    When(piecc =   0) Then Nop   /* not under pie */
  24289.    When(piecc =  12) Then Nop   /* no piecheck cmd ==> not under pie */
  24290.    When(piecc = 241) Then Nop   /* pie session 1 */
  24291.    Otherwise         prof = 'IS1PROF'
  24292.    End  /* select */
  24293.  
  24294. "CONTROL ERRORS RETURN"
  24295. "TBOPEN NNLIST WRITE LIBRARY("prof") SHARE"
  24296. If Rc > 8 then signal ispf_error
  24297. If Rc = 0 Then "TBTOP NNLIST"
  24298. Else Do
  24299.    "TBCREATE NNLIST WRITE LIBRARY("prof") NAMES(SERVER NEWSRC)"
  24300.    If Rc ^= 0 Then signal ispf_error
  24301.    End
  24302. csr = "" 
  24303. dispcc = 0
  24304.  
  24305.  
  24306. Do Forever
  24307.    "TBQUERY NNLIST ROWNUM(ROWNUM)"
  24308.    If Rc > 8 then signal ispf_error
  24309.    If rownum = 0 Then Do
  24310.       server = ""
  24311.       newsrc = ""
  24312.       "TBADD NNLIST"
  24313.       If RC > 8 then signal ispf_error
  24314.       csr = "CURSOR(SERVER) CSRROW(1)"
  24315.       End
  24316.  
  24317.    "TBTOP   NNLIST"
  24318.    If Rc > 8 then signal ispf_error
  24319.    nnsel = ""
  24320.    If dispcc = 4 Then "TBDISPL NNLIST"
  24321.                  Else "TBDISPL NNLIST PANEL("panel_name")" csr
  24322.    dispcc = Rc
  24323.    csr = ""
  24324.  
  24325.    If dispcc = 8 Then Do
  24326.       "TBCLOSE NNLIST PAD(50) LIBRARY("prof")"
  24327.       If Rc > 8 then signal ispf_error
  24328.       return 0
  24329.       End
  24330.  
  24331.    If (dispcc ^= 0 & dispcc ^= 4) Then Do
  24332.       Say "TBDISPL Rc =" dispcc
  24333.       Say zerrsm
  24334.       Say zerrlm
  24335.       "TBCLOSE NNLIST PAD(50) LIBRARY("prof")"
  24336.       If Rc > 8 then signal ispf_error
  24337.       return 16
  24338.       End
  24339.  
  24340.    If zcmd = "" Then Do  /* look for line commands */
  24341.       Upper nnsel
  24342.       Select
  24343.          When (nnsel = "" ) Then "TBPUT NNLIST"
  24344.          When (nnsel = "D") Then Do
  24345.             /*
  24346.             "CONTROL DISPLAY SAVE"
  24347.             "DISPLAY PANEL(NNLDEL)"
  24348.             delcc = Rc
  24349.             "CONTROL DISPLAY RESTORE"
  24350.             if delcc > 8 then signal ispf_error
  24351.             If delcc = 0 Then */ "TBDELETE NNLIST"
  24352.             Iterate
  24353.             End
  24354.          When (nnsel = "I") Then Do
  24355.             server = ""
  24356.             newsrc = ""
  24357.             "TBADD NNLIST"
  24358.             if Rc > 8 then signal ispf_error
  24359.             "TBQUERY NNLIST POSITION(NEWROW)"
  24360.             if Rc > 8 then signal ispf_error
  24361.             csr = "CURSOR(SERVER) CSRROW("newrow")"
  24362.             Iterate
  24363.             End
  24364.          When (nnsel = "R") Then Do
  24365.             "TBADD NNLIST"
  24366.             if Rc > 8 then signal ispf_error
  24367.             "TBQUERY NNLIST POSITION(NEWROW)"
  24368.             if Rc > 8 then signal ispf_error
  24369.             csr = "CURSOR(SERVER) CSRROW("newrow")"
  24370.             Iterate
  24371.             End
  24372.          When (nnsel = "S") Then Do
  24373.             "TBCLOSE NNLIST PAD(50) LIBRARY("prof")"
  24374.             cc = Rc
  24375.             if cc > 8 then signal ispf_error
  24376.             If cc ^= 0 Then Say "TBCLOSE rc =" cc
  24377.             operands = ""
  24378.             If server ^= "" Then operands =          "SERVER("server")"
  24379.             If newsrc ^= "" Then operands = operands "NEWSRC("newsrc")"
  24380.             Address TSO nnmvs_command operands
  24381.             return 0
  24382.             End
  24383.          Otherwise Do
  24384.             badsel = nnsel
  24385.             zerrsm   = badsel "invalid"
  24386.             zerrlm   = badsel "is not a valid line command"
  24387.             zerralrm = "YES"
  24388.             zerrhm   = "*"
  24389.             "SETMSG MSG(ISRZ002)"
  24390.             If Rc > 8 Then signal ispf_error
  24391.             End
  24392.          End /* select */
  24393.       End  /* zcmd = "" */
  24394. Else Do  /* zcmd ^= "" */
  24395.       badcmd = Word(zcmd,1)
  24396.       zerrsm   = "Invalid command"
  24397.       zerrlm   = badcmd "is not a valid primary command"
  24398.       zerralrm = "YES"
  24399.       zerrhm   = "*"
  24400.       "SETMSG MSG(ISRZ002)"
  24401.       If Rc > 8 Then signal ispf_error
  24402.       End  /* zcmd ^= "" */
  24403.    End  /* main loop */
  24404.  
  24405. return 0 
  24406.  
  24407. /* ISPF dialog error handling. */
  24408.  
  24409. ispf_error:
  24410. address ISPEXEC "DISPLAY PANEL(ISPTERM)"
  24411. signal cleanup
  24412.  
  24413. error:failure:halt:say "NNMVSL: Severe lossage."
  24414. say "Statement:" sourceline(sigl)
  24415. exit
  24416. ./   ADD NAME=NNMVSP,SSI=010D0033
  24417. /* REXX. Syntax:  NNMVS  (see XPROC for the rest)   */
  24418.  
  24419. /*********************************************************************/
  24420. /*                                                                   */
  24421. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     */
  24422. /*                                                                   */
  24423. /* This software is provided on an "AS IS" basis.  All warranties,   */
  24424. /* including the implied warranties of merchantability and fitness,  */
  24425. /* are expressly denied.                                             */
  24426. /*                                                                   */
  24427. /* Provided this copyright notice is included, this software may     */
  24428. /* be freely distributed and not offered for sale.                   */
  24429. /*                                                                   */
  24430. /* Changes or modifications may be made and used only by the maker   */
  24431. /* of same, and not further distributed.  Such modifications should  */
  24432. /* be mailed to the author for consideration for addition to the     */
  24433. /* software and incorporation in subsequent releases.                */
  24434. /*                                                                   */
  24435. /*********************************************************************/
  24436.  
  24437. /* *** Customize the following lines for your installation. *** */
  24438. /*                                                              */
  24439. /* If nnmpanel is set to "", it will not be LIBDEF'd.           */
  24440. /* If nnmload  is set to "", it will not be LIBDEF'd.           */
  24441. /*                                                              */
  24442.  
  24443. save_prompt = prompt("ON")
  24444. "XPROC 0 TEST DEBUG FORCE NEW OLD BATCH BATCHIN(*) BATCHOUT(*)
  24445.          SERVER() GROUP() NEWSRC() OPTION() REGISTERSTATUS()"
  24446. if rc <> 0 then exit rc
  24447. call prompt save_prompt
  24448.  
  24449. select
  24450.  when new = "NEW" then do
  24451.   nnmprefix      = "NNMVS"     /* or use "new" (testing) parameters */
  24452.   nnmpanelsuffix = "ISPPLIB"   /* or use "new" (testing) parameters */
  24453.   nnmloadsuffix  = "LOAD"      /* or use "new" (testing) parameters */
  24454.   nnmlmod        = "NNMMAIN"   /* or use "new" (testing) parameters */
  24455.  end
  24456.  when old = "OLD" then do
  24457.   nnmprefix      = "NNMVS"     /* or use "old" (backup) parameters */
  24458.   nnmpanelsuffix = "ISPPLIB"   /* or use "old" (backup) parameters */
  24459.   nnmloadsuffix  = "LOAD"      /* or use "old" (backup) parameters */
  24460.   nnmlmod        = "NNMMAIN"   /* or use "old" (backup) parameters */
  24461.  end
  24462.  otherwise do
  24463.   nnmprefix      = "NNMVS"
  24464.   nnmpanelsuffix = "ISPPLIB"
  24465.   nnmloadsuffix  = "LOAD"
  24466.   nnmlmod        = "NNMMAIN"
  24467.  end
  24468. end
  24469.  
  24470. nnmpanel       = nnmprefix"."nnmpanelsuffix
  24471. nnmload        = nnmprefix"."nnmloadsuffix
  24472. nnmappl        = "ISR"
  24473. batchhelp      = "'"nnmprefix".HELP.TEXT'"
  24474. nnmvswizard    = "Steve Bacher <seb@draper.com>"   /* next of kin */
  24475. nnmvsmeister   = ""               /* TSOID of NNMVS's Big Brother */
  24476.  
  24477. trace off
  24478. signal on novalue
  24479. libdeffed = 0
  24480.  
  24481. if batch = "" then do
  24482.  "ISPQRY"
  24483.  if rc > 0 then do
  24484.   parse arg args
  24485.   parse source . . execname . execds .
  24486.   if execds = "?" then
  24487.    icmd = "%"execname args
  24488.   else
  24489.    icmd = "EX '"execds"("execname")'" quote(args)
  24490.   call startispf "NEWAPPL("nnmappl") CMD("icmd")"
  24491.   exit
  24492.  end
  24493. end
  24494.  
  24495. signal on failure
  24496. signal on halt
  24497.  
  24498. if option <> "" then do
  24499.  if length(option) <> 1 | pos(option,"TDB") <> 0 then do
  24500.   say "NNMVS: Invalid option, "option"."
  24501.   exit 12
  24502.  end
  24503.  if server = "" then do
  24504.   say "NNMVS: SERVER is required when OPTION is specified."
  24505.   exit 12
  24506.  end
  24507.  if newsrc = "" then do
  24508.   say "NNMVS: NEWSRC is required when OPTION is specified."
  24509.   exit 12
  24510.  end
  24511.  if option = "G" & group = "" then do
  24512.   say "NNMVS: GROUP is required when OPTION(G) is specified."
  24513.   exit 12
  24514.  end
  24515.  if registerstatus = "" then registerstatus = "PROMPT"
  24516. end
  24517.  
  24518. testparm = "-"
  24519. if test  = "TEST"  then testparm = testparm || "t"
  24520. if debug = "DEBUG" then testparm = testparm || "d"
  24521. if batch = "BATCH" then testparm = testparm || "b"
  24522.  
  24523. if find_iucvmult() <> 0 then do
  24524.  say,
  24525. "A TCP/IP socket application may be active elsewhere in your session."
  24526.  if force = "FORCE" then do
  24527.   say "Proceeding anyhow, because you specified the FORCE keyword."
  24528.  end
  24529.  else do 
  24530.   say "Please terminate the other application before trying this one."
  24531.   say "Or, if you are sure it's OK, try again with the FORCE keyword."
  24532.   exit 8 
  24533.  end
  24534. end
  24535.  
  24536. if batch <> "" then call nnm_batch
  24537. else do
  24538.  call libdef
  24539.  call nnm_dialog
  24540. end
  24541.  
  24542. cleanup: 
  24543. if libdeffed then call unlibdef
  24544. exit
  24545.  
  24546. error:    say "NNMVS:  Lossage has occurred."
  24547.           say "Statement:" sourceline(sigl)
  24548.           if nnmvswizard <> "" then say "Please notify" nnmvswizard"."
  24549.           signal cleanup
  24550. failure:  say "NNMVS:  A failure has eventuated."
  24551.           say "Statement:" sourceline(sigl)
  24552.           if nnmvswizard <> "" then say "Please notify" nnmvswizard"."
  24553.           signal cleanup
  24554. halt:     say "NNMVS:  A halt has been detected."
  24555.           signal cleanup
  24556.  
  24557. nnm_dialog:
  24558.  
  24559. /* SERVER(*) --> (USC) Leonard Woren's server-table dialog */
  24560.  
  24561. if server = "*" | newsrc = "*" then do
  24562.  nnmvsl_cmd = "%NNMVSL" new old
  24563.  address ISPEXEC "SELECT CMD("nnmvsl_cmd") PASSLIB NEWAPPL("nnmappl")"
  24564.  return
  24565. end
  24566.  
  24567. vputvars = ""
  24568.  
  24569. if server <> "" then do
  24570.  nnserver = server
  24571.  vputvars = vputvars "NNSERVER"
  24572. end
  24573.  
  24574. if group <> "" | option = "G" then do
  24575.  nngroupi = group
  24576.  vputvars = vputvars "NNGROUPI"
  24577. end
  24578.  
  24579. if newsrc <> "" then do
  24580.  nnnewsrf = newsrc
  24581.  if left(newsrc,1) = "'" then nnnewsrc = strip(newsrc,"B","'")
  24582.  else nnnewsrc = sysvar("SYSPREF")"."newsrc
  24583.  vputvars = vputvars "NNNEWSRF NNNEWSRC"
  24584. end
  24585.  
  24586. if registerstatus <> "" then do
  24587.  nnregnng = left(registerstatus,1)
  24588.  vputvars = vputvars "NNREGNNG"
  24589. end
  24590.  
  24591. if vputvars <> "" then do
  24592.  address ISPEXEC "VPUT ("vputvars") PROFILE"
  24593. end
  24594.  
  24595. if option <> "" then do
  24596.  testparm = testparm || option
  24597. end
  24598.  
  24599. call let_me_know
  24600.  
  24601. zerrmsg = ""
  24602. zerrsm  = ""
  24603. zerrlm  = ""
  24604.  
  24605. if nnmload = "" then do
  24606.  address ISPEXEC "SELECT NEWAPPL("nnmappl") PASSLIB" ,
  24607.                  "PGM("nnmlmod") PARM("testparm")"
  24608. end
  24609. else do
  24610.  command = "CALL '"nnmload"("nnmlmod")'" quote(testparm)
  24611.  address ISPEXEC "SELECT NEWAPPL("nnmappl") PASSLIB CMD("command")"
  24612. end
  24613.  
  24614. if rc <> 0 then say "Return code from" nnmlmod "program is" rc
  24615.  
  24616. address ISPEXEC "VGET (ZERRSM ZERRLM)"
  24617. if zerrsm  <> "" then do
  24618.  say zerrmsg":" zerrsm
  24619.  say zerrlm
  24620. end
  24621.  
  24622. return
  24623.  
  24624. nnm_batch:
  24625.  
  24626. if newsrc = "" then do
  24627.  say "NNMVS: NEWSRC is required when BATCH is specified."
  24628.  exit 12 
  24629. end
  24630.  
  24631. if server <> "" ,
  24632.  | group  <> "" ,
  24633.  | registerstatus <> "" ,
  24634.  | option <> "" then do
  24635.  say "NNMVS: SERVER, GROUP, OPTION, REGISTERSTATUS not valid",
  24636.             "when BATCH is specified."
  24637.  exit 12 
  24638. end
  24639.  
  24640. address TSO "ALLOC FI(NNBATIN)  DA("batchin")  SHR REU"
  24641. if rc <> 0 then return
  24642. address TSO "ALLOC FI(NNBATOUT) DA("batchout") OLD REU"
  24643. if rc <> 0 then return
  24644. address TSO "ALLOC FI(NNBATHLP) DA("batchhelp") SHR REU"
  24645. if rc <> 0 then return
  24646. address TSO "ALLOC FI(NNNEWSRC) DA("newsrc")   OLD REU"
  24647. if rc <> 0 then return
  24648.  
  24649. call let_me_know "BATCH"
  24650.  
  24651. address TSO "CALL '"nnmload"("nnmlmod")'" quote(testparm)
  24652. nrc = rc 
  24653. address TSO "FREE FI(NNBATIN NNBATOUT NNBATHLP NNNEWSRC)"
  24654.  
  24655. if nrc <> 0 then say "Return code from" nnmlmod "program is" nrc
  24656.  
  24657. return
  24658.  
  24659. let_me_know:
  24660. if nnmvsmeister = "" | nnmvsmeister = userid() then return
  24661. parse arg letarg
  24662. parse source . . execname . execds .
  24663. call outtrap "X."
  24664. address TSO,
  24665.  "SEND" quote(execds"("execname")" letarg date("U") time()" "),
  24666.         "U("nnmvsmeister") LOGON"
  24667. call outtrap "OFF"
  24668. return
  24669.  
  24670. libdef:
  24671. if nnmpanel <> "" then do
  24672.  address ISPEXEC "LIBDEF ISPPLIB DATASET ID('"nnmpanel"')"
  24673.  if rc <> 0 then do; call ispf_error rc; exit rc; end
  24674. end
  24675. if nnmload <> "" then do
  24676.  address ISPEXEC "LIBDEF ISPLLIB DATASET ID('"nnmload"')"
  24677.  if rc <> 0 then do; call ispf_error rc; exit rc; end
  24678. end
  24679. libdeffed = 1
  24680. return
  24681.  
  24682. unlibdef:
  24683. if nnmload <> "" then do
  24684.  address ISPEXEC "LIBDEF ISPLLIB DATASET"
  24685.  if rc <> 0 then call ispf_error rc
  24686. end
  24687. if nnmpanel <> "" then do
  24688.  address ISPEXEC "LIBDEF ISPPLIB DATASET"
  24689.  if rc <> 0 then call ispf_error rc
  24690. end
  24691. libdeffed = 0
  24692. return
  24693.  
  24694. ispf_error: parse arg ispfrc
  24695.  
  24696. say "NNMVS: ISPF dialog service error detected..."
  24697. say
  24698. say zerrmsg":" zerrsm
  24699. say zerrlm
  24700. say
  24701.  
  24702. return ispfrc
  24703.  
  24704. /*
  24705.  * The following function starts ISPF from READY mode.
  24706.  * Beware:  splitting the screen starts up an identical copy of the
  24707.  *          application, which may not be desirable.
  24708.  */
  24709.  
  24710. startispf: parse arg string
  24711. "ISPSTART" string
  24712. return
  24713.  
  24714. /* The following function enquotes a string. */
  24715.  
  24716. quote: parse arg string
  24717. ix = 1
  24718. do forever
  24719.  ix = pos("'",string,ix)
  24720.  if ix = 0 then return "'"string"'"
  24721.  string = insert("'",string,ix)
  24722.  ix=ix+2 
  24723. end
  24724.  
  24725. /* The following function scans the job pack queues for IUCVMULT and
  24726.  * returns with an error code if IUCVMULT is already loaded under a
  24727.  * different TCB. This can only happen under PIE MultiTSO or a
  24728.  * similar product that makes multiple job step TCB's.
  24729.  */
  24730.  
  24731. find_iucvmult: procedure
  24732.  
  24733. call nnmfiucv
  24734.  
  24735. return result
  24736.  
  24737. ./ ENDUP 
  24738. ?!
  24739. //H        EXEC NNLOAD,TRK1='6',TO='H'
  24740. //SYSIN    DD DATA,DLM='?!'
  24741. ./   ADD NAME=NN,SSI=01630044
  24742.  
  24743.  /********************************************************************/
  24744.  /*                                                                  */
  24745.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  24746.  /*                                                                  */
  24747.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  24748.  /*                                                                  */
  24749.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  24750.  /* including the implied warranties of merchantability and fitness, */
  24751.  /* are expressly denied.                                            */
  24752.  /*                                                                  */
  24753.  /* Provided this copyright notice is included, this software may    */
  24754.  /* be freely distributed and not offered for sale.                  */
  24755.  /*                                                                  */
  24756.  /* Changes or modifications may be made and used only by the maker  */
  24757.  /* of same, and not further distributed.  Such modifications should */
  24758.  /* be mailed to the author for consideration for addition to the    */
  24759.  /* software and incorporation in subsequent releases.               */
  24760.  /*                                                                  */
  24761.  /********************************************************************/
  24762.  
  24763. /* --------------------- "nn.h" include member --------------------- */
  24764.  
  24765. #pragma linkage(ispexec,OS)
  24766. #pragma linkage(isplink,OS)
  24767. #pragma linkage(ikjeff18,OS)
  24768.  
  24769. /****** Installation-customized defines. *****************************/
  24770.  
  24771. #include "nnuser.h"
  24772.  
  24773. #ifndef  C370V1
  24774. #ifndef  C370V2
  24775. #ifndef  SASC
  24776.  install_error_neither_C370V1_C370V2_nor_SASC_was_defined;
  24777. #endif
  24778. #endif
  24779. #endif
  24780.  
  24781. #ifndef  TCPIPV1
  24782. #ifndef  TCPIPV2
  24783. #ifndef  SNSTCP
  24784.  install_error_neither_TCPIPV1_nor_TCPIPV2_nor_SNSTCP_was_defined;
  24785. #endif
  24786. #endif
  24787. #endif
  24788.  
  24789. #ifndef  ISPFV2
  24790. #ifndef  ISPFV3
  24791.  install_error_neither_ISPFV2_nor_ISPFV3_was_defined;
  24792. #endif
  24793. #endif
  24794.  
  24795. #define  MVS
  24796.  
  24797. #ifdef C370V2
  24798. #pragma checkout(suspend)
  24799. #endif
  24800.  
  24801. /****** Clean up compiler warnings BEFORE time.h gets 'em ************/
  24802.  
  24803. #ifndef  SASC
  24804. #define  localtime            LOCALTIM
  24805. #endif
  24806.  
  24807. /****** Include all header files that are necessary. *****************/
  24808.  
  24809. #include <manifest.h>
  24810. #include <sys/types.h>
  24811. #include <sys/socket.h>
  24812. #include <netdb.h>
  24813. #include <netinet/in.h>
  24814. #include <sys/uio.h>
  24815. #include <sys/ioctl.h>
  24816. /*
  24817. #include <tcperrno.h>
  24818. */
  24819. #include <ctype.h>
  24820. #include <errno.h>
  24821. #include <limits.h>
  24822. #include <setjmp.h>
  24823. #include <stdio.h>
  24824. #include <stdarg.h>
  24825. #include <stdlib.h>
  24826. #include <string.h>
  24827. #include <stddef.h>
  24828. #include <time.h>
  24829. /*
  24830. #include <signal.h>
  24831. */
  24832.  
  24833. #ifndef  SASC
  24834. #include <ctest.h>
  24835. #endif
  24836.  
  24837. #ifdef   SASC
  24838. #include "nnsasc.h"
  24839. #endif
  24840.  
  24841. /****** Version-dependent stuff **************************************/
  24842.  
  24843. #ifdef   C370V1
  24844. #undef   FETCH
  24845. #endif
  24846.  
  24847. #ifdef   C370V2
  24848. #define  FETCH
  24849. #endif
  24850.  
  24851. #ifdef   TCPIPV1
  24852. #define  TCP_DEBUG            tcp_debug
  24853. #endif
  24854.  
  24855. #ifdef   TCPIPV2
  24856. #define  TCP_DEBUG            sock_debug
  24857. #endif
  24858.  
  24859. #ifdef   DEBUG
  24860. #define  TCP_DEBUG_ON         TCP_DEBUG(1)
  24861. #define  TCP_DEBUG_OFF        TCP_DEBUG(0)
  24862. #else
  24863. #define  TCP_DEBUG_ON         /* */
  24864. #define  TCP_DEBUG_OFF        /* */
  24865. #endif
  24866.  
  24867. #ifdef   ISPFV3
  24868. #define  ZERRLM_SIZE          513
  24869. #else
  24870. #define  ZERRLM_SIZE          73
  24871. #endif
  24872.  
  24873. /****** Preprocessor bookkeeping *************************************/
  24874.  
  24875. #ifndef  MAX
  24876. #define  MAX(A,B)             ((A) > (B) ? (A) : (B))
  24877. #endif
  24878. #ifndef  MIN
  24879. #define  MIN(A,B)             ((A) < (B) ? (A) : (B))
  24880. #endif
  24881.  
  24882. #define  Bool                 char
  24883. #define  Fool                 unsigned int /* for function arguments */
  24884.  
  24885. #define  COMMANDSIZE          12
  24886.  
  24887. #define  READ_BYTES           1024
  24888. #define  SERVER_BUF_MSGSIZE   1024
  24889. #define  CLIENT_BUF_MSGSIZE   1024
  24890. #define  TEXT_BYTES           1024
  24891. #define  INTERNET_SIZE        256
  24892.  
  24893. #define  GROUP_NAME_SIZE      255
  24894.  
  24895. #define  NNTP_PORT_NUMBER     119
  24896.  
  24897. #define  SOCKET_GETCHAR_ERROR (-1)
  24898. #define  SOCKET_NO_MORE       (-2)
  24899. #define  SOCKET_READ_NOTHING  (-3)
  24900.  
  24901. #define  NO_NNTP_MESSAGE_NUM  (-1)
  24902. #define  NO_VALUE             (-1)
  24903. #define  PHONY_NEWS_ARTICLE   (-1)
  24904.  
  24905. #define  Rstruc               register struct
  24906.  
  24907. #define  EQUAL                !strcmp
  24908. #define  UNEQUAL              strcmp
  24909.  
  24910. #define  NEWSRC_ORDER         'N'
  24911. #define  NNTP_LIST_ORDER      'L'
  24912. #define  ALPHABETICAL_ORDER   'A'
  24913.  
  24914. #define  FIND_NEXT            'N'
  24915. #define  FIND_FIRST           'F'
  24916. #define  FIND_LAST            'L'
  24917. #define  FIND_PREV            'P'
  24918. #define  FIND_ALL             'A'
  24919. #define  FIND_CHARS           '\0'
  24920. #define  FIND_WORD            'W'
  24921. #define  FIND_PREFIX          'P'
  24922. #define  FIND_SUFFIX          'S'
  24923. #define  FIND_CAPS            '\0'
  24924. #define  FIND_ASIS            'A'
  24925. #define  FIND_HEX             'X'
  24926. #define  FIND_GENERIC         'P'
  24927. #define  FIND_BADFORM         '\0'
  24928. #define  FIND_UNQUOTED        'U'
  24929. #define  FIND_QUOTED          'Q'
  24930. #define  FIND_C               'C'
  24931. #define  FIND_X               'X'
  24932. #define  FIND_T               'T'
  24933. #define  FIND_P               'P'
  24934.  
  24935. #define  MAX_INT               (int)0x7fffffff
  24936. #define  LOCATE_INT            (int)0x7ffffffe
  24937.  
  24938. #define  SELECTION_ALL        'A'
  24939. #define  SELECTION_REG        'R'
  24940. #define  SELECTION_NNTP       'P'
  24941. #define  SELECTION_GROUP      'G'
  24942. #define  SELECTION_LIST       'L'
  24943. #define  SELECTION_NEWG       'N'
  24944. #define  SELECTION_OPTS       'O'
  24945. #define  SELECTION_EXIT       'X'
  24946. #define  SELECTION_LIST_DISCONNECT  'Z'
  24947.  
  24948. #define  NO_ACTION            '\0'
  24949. #define  READ                 'R'
  24950. #define  RETRIEVED            'V'
  24951. #define  EXTRACTED            'X'
  24952. #define  PRINTED              'P'
  24953. #define  UNREAD               'U'
  24954. #define  MISSING              'M'
  24955. #define  ERROR                'E'
  24956. #define  CANCELLED            'C'
  24957.  
  24958. #define  CARRIAGE_RETURN      ('\r')
  24959.  
  24960. #ifdef   MVS
  24961. #ifdef   I370
  24962. #define  LINE_FEED            (0x15)
  24963. #else
  24964. #define  LINE_FEED            (0x25)
  24965. #endif
  24966. #else
  24967. #define  LINE_FEED            (0x0a)
  24968. #endif
  24969.  
  24970. #ifdef   MVS
  24971. #ifdef   SNSTCPIP
  24972. #define  EtoA                 etoa
  24973. #define  AtoE                 atoe
  24974. #else
  24975. #ifdef   I370
  24976. #define  EtoA                 htoncs
  24977. #define  AtoE                 ntohcs
  24978. #else
  24979. #define  EtoA(x)              ebcdictoascii[x]
  24980. #define  AtoE(x)              asciitoebcdic[x]
  24981. #define  ebcdictoascii        ebcdicto
  24982. #define  asciitoebcdic        asciitoe
  24983. #endif
  24984. #endif
  24985. #endif
  24986.  
  24987. #ifdef SNSTCPIP
  24988. #define EBCDIC_TO_ASCII(A,B) EtoA(A,B)
  24989. #define ASCII_TO_EBCDIC(A,B) AtoE(A,B)
  24990. #else
  24991. #define EBCDIC_TO_ASCII(A,B) {int _i; \
  24992.                               for (_i=0; _i<(B); ++_i) \
  24993.                                   (A)[_i] = EtoA((A)[_i]); \
  24994.                              }
  24995. #define ASCII_TO_EBCDIC(A,B) {int _i; \
  24996.                               for (_i=0; _i<(B); ++_i) \
  24997.                                   (A)[_i] = AtoE((A)[_i]); \
  24998.                              }
  24999. #endif
  25000.  
  25001. #ifdef TCPIPV1
  25002. #define REPORT_TCP_ERROR(A)  /* */
  25003. #endif
  25004.  
  25005. #ifdef TCPIPV2
  25006. #define REPORT_TCP_ERROR(A)  tcperror(A)
  25007. #endif
  25008.  
  25009. #ifdef SNSTCPIP
  25010. #define REPORT_TCP_ERROR(A)  fprintf(stderr,\
  25011.                                     "\nTCP error on %s: errno = %d\n",\
  25012.                                     A,GET_ERRNO)
  25013. #endif
  25014.  
  25015. #ifdef SNSTCPIP
  25016. #define Accept(A,B,C)        accept((A),(struct sockaddr *)(B),(C))
  25017. #define Bind(A,B,C)          bind((A),(struct sockaddr *)(B),(C))
  25018. #define Connect(A,B,C)       connect((A),(struct sockaddr *)(B),(C))
  25019. #define Gethostbyaddr(A,B,C) gethostbyaddr((char *)(A),(B),(C))
  25020. #define Getpeername(A,B,C)   getpeername((A),(struct sockaddr *)(B),(C))
  25021. #define Getsockopt(A,B,C,D)  getsockopt((A),(B),(char *)(C),(D))
  25022. #define EWOULDBLOCK          ESWOULDBLOCK
  25023. #define errno                GET_ERRNO
  25024. #else
  25025. #define Accept               accept
  25026. #define Bind                 bind
  25027. #define Connect              connect
  25028. #define Gethostbyaddr        gethostbyaddr
  25029. #define Getpeername          getpeername
  25030. #define Getsockopt           getsockopt
  25031. #endif
  25032.  
  25033. #ifdef   FETCH
  25034. #define  ISPLINK              (np->isplink_pointer)
  25035. #define  ISPEXEC              (np->ispexec_pointer)
  25036. #else
  25037. #define  ISPLINK              isplink
  25038. #define  ISPEXEC              ispexec
  25039. #endif
  25040.  
  25041. #ifndef I370
  25042.  
  25043. #define  WRITE_FILEMODE     "w,recfm=vb,lrecl=259,blksize=6233"
  25044. #define  APPEND_FILEMODE    "a,recfm=vb,lrecl=259,blksize=6233"
  25045. #define  SYSOUT_FILEMODE    "w,recfm=vba,lrecl=133"
  25046. #define  FILEMODE             "recfm=vb,lrecl=259,blksize=6233"
  25047. #define  FILEMODE_A           "recfm=vba,lrecl=133"
  25048.  
  25049. #define  OPEN_TEXT_FILE_FOR_WRITE(F)  \
  25050.          fopen((F),WRITE_FILEMODE)
  25051.  
  25052. #define  OPEN_TEXT_FILE_FOR_APPEND(F)  \
  25053.          fopen((F),APPEND_FILEMODE)
  25054.  
  25055. #define  OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(F,B)  \
  25056.          fopen((F),(B) ? APPEND_FILEMODE : WRITE_FILEMODE)
  25057.  
  25058. #define  OPEN_OUTPUT_FILE_FOR_WRITE_OR_APPEND(F,B)  \
  25059.          fopen((F),(B) ? "a" : WRITE_FILEMODE)
  25060.  
  25061. #define  OPEN_SYSOUT_FILE(F)  \
  25062.          fopen((F),SYSOUT_FILEMODE)
  25063.  
  25064. #define  TEST_IF_FILE_EXISTS(P,F)  (P=fopen((F),"r"))
  25065. #define  CLEANUP_IF_FILE_EXISTS(P) (void)fclose(P)
  25066.  
  25067. #else
  25068.  
  25069. #define  WRITE_FILEMODE     "w,recfm=v,lrecl=255,blksize=6233"
  25070. #define  APPEND_FILEMODE    "a,recfm=v,lrecl=255,blksize=6233"
  25071. #define  SYSOUT_FILEMODE    "w,recfm=va,lrecl=133"
  25072. #define  FILEMODE             "recfm=v,lrecl=255,blksize=6233"
  25073. #define  FILEMODE_A           "recfm=va,lrecl=133"
  25074.  
  25075. #define  OPEN_TEXT_FILE_FOR_WRITE(F)  \
  25076.          afopen((F),"w","seq",FILEMODE)
  25077.  
  25078. #define  OPEN_TEXT_FILE_FOR_APPEND(F)  \
  25079.          afopen((F),"a","seq",FILEMODE)
  25080.  
  25081. #define  OPEN_TEXT_FILE_FOR_WRITE_OR_APPEND(F,B)  \
  25082.          afopen((F),(B)?"a":"w","seq",FILEMODE)
  25083.  
  25084. #define  OPEN_OUTPUT_FILE_FOR_WRITE_OR_APPEND(F,B)  \
  25085.          afopen((F),(B)?"a":"w","seq",FILEMODE)
  25086.  
  25087. #define  OPEN_SYSOUT_FILE(F)  \
  25088.          afopen((F),"w","seq",FILEMODE_A)
  25089.  
  25090. #define  TEST_IF_FILE_EXISTS(F,P)  (access((F),0) == 0)
  25091. #define  CLEANUP_IF_FILE_EXISTS(P) /* */
  25092.  
  25093. #endif
  25094.  
  25095. #define ebdtoasc(C) {char *__cp;\
  25096.                      for(__cp = C;*__cp;__cp++) *__cp = EtoA(*__cp);}
  25097.  
  25098. #define asctoebd(C) {char *__cp;\
  25099.                      for(__cp = C;*__cp;__cp++) *__cp = AtoE(*__cp);}
  25100.  
  25101. #define uppercase_in_place(C) {char *__cp;\
  25102.                      for(__cp=C;*__cp;__cp++) *__cp = toupper(*__cp);}
  25103.  
  25104. #define lowercase_in_place(C) {char *__cp;\
  25105.                      for(__cp=C;*__cp;__cp++) *__cp = tolower(*__cp);}
  25106.  
  25107. #define strip_trailing_in_place(C) {char *__cp;\
  25108.                      for(__cp=strchr((C),'\0');\
  25109.                          __cp>C && isspace(*(__cp-1)); __cp--);\
  25110.                      *__cp='\0';}
  25111.  
  25112. #define uppercase_and_strip_trailing_in_place(C) {char *__cp;\
  25113.                      for(__cp=C;*__cp;__cp++) *__cp = toupper(*__cp);\
  25114.                      for(; __cp>C && isspace(*(__cp-1)); __cp--);\
  25115.                      *__cp='\0';}
  25116.  
  25117. #define lowercase_and_strip_trailing_in_place(C) {char *__cp;\
  25118.                      for(__cp=C;*__cp;__cp++) *__cp = tolower(*__cp);\
  25119.                      for(; __cp>C && isspace(*(__cp-1)); __cp--);\
  25120.                      *__cp='\0';}
  25121.  
  25122. #define copy_uppercase(A,B) {char *__cA,*__cB;\
  25123.                      for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
  25124.                          *__cA = toupper(*__cB);\
  25125.                      *__cA='\0';}
  25126.  
  25127. #define copy_lowercase(A,B) {char *__cA,*__cB;\
  25128.                      for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
  25129.                          *__cA = tolower(*__cB);\
  25130.                      *__cA='\0';}
  25131.  
  25132. #define copy_uppercase_and_strip_trailing(A,B,C) {char *__cA,*__cB;\
  25133.                      for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
  25134.                          *__cA = toupper(*__cB);\
  25135.                      for (; __cA>A && isspace(*(__cA-1)); __cA--);\
  25136.                      *__cA='\0';C=__cA;}
  25137.  
  25138. #define copy_lowercase_and_strip_trailing(A,B,C) {char *__cA,*__cB;\
  25139.                      for (__cA=A,__cB=B; *__cB;__cA++,__cB++)\
  25140.                          *__cA = tolower(*__cB);\
  25141.                      for (; __cA>A && isspace(*(__cA-1)); __cA--);\
  25142.                      *__cA='\0';C=__cA;}
  25143.  
  25144. #define skip_whitespace(C)        (C) + strspn((C)," \t")
  25145. #define skip_ISPF_whitespace(C)   (C) + strspn((C)," ,\t")
  25146. #define find_whitespace(A,B)      if (!(A=strpbrk((B)," \t")))\
  25147.                                      A = strchr((B),'\0');
  25148. #define find_ISPF_whitespace(A,B) if (!(A=strpbrk((B)," ,\t")))\
  25149.                                      A = strchr((B),'\0');
  25150.  
  25151. #define  DATAOUT_LOW          0x01
  25152. #define  DATAOUT_HIGH         0x02
  25153. #define  DATAIN_LOW           0x03
  25154. #define  DATAIN_HIGH          0x04
  25155. #define  DATAOUT_BLUE         DATAOUT_LOW
  25156. #define  DATAOUT_GREEN        0x05
  25157. #define  DATAOUT_PINK         0x06
  25158. #define  DATAOUT_RED          0x07
  25159. #define  DATAOUT_TURQ         0x08
  25160. #define  DATAOUT_WHITE        DATAOUT_HIGH
  25161. #define  DATAOUT_YELLOW       0x09
  25162. #define  DATAIN_BLUE          0x0a
  25163. #define  DATAIN_GREEN         DATAIN_LOW
  25164. #define  DATAIN_PINK          0x0b
  25165. #define  DATAIN_RED           DATAIN_HIGH
  25166. #define  DATAIN_TURQ          0x0c
  25167. #define  DATAIN_WHITE         0x0d
  25168. #define  DATAIN_YELLOW        0x0e
  25169.  
  25170. #define  S99VRBAL  0x01             /* ALLOCATION                    */
  25171. #define  S99VRBUN  0x02             /* UNALLOCATION                  */
  25172. #define  S99VRBCC  0x03             /* CONCATENATION                 */
  25173. #define  S99VRBDC  0x04             /* DECONCATENATION               */
  25174. #define  S99VRBRI  0x05             /* REMOVE IN-USE                 */
  25175. #define  S99VRBDN  0x06             /* DDNAME ALLOCATION             */
  25176. #define  S99VRBIN  0x07             /* INFORMATION RETRIEVAL         */
  25177. #define  S99NOCNV  0x40             /* ALLOC FUNCTION-DO NOT USE AN  */
  25178.                                     /* EXISTING ALLOCATION TO SATISFY*/
  25179.                                     /* THE REQUEST                   */
  25180. #define  DALDDNAM   0x0001          /* DDNAME                        */
  25181. #define  DALDSNAM   0x0002          /* DSNAME                        */
  25182. #define  DALMEMBR   0x0003          /* MEMBER NAME                   */
  25183. #define  DALSTATS   0x0004          /* DATA SET STATUS               */
  25184. #define  DALNDISP   0x0005          /* DATA SET DISPOSITION          */
  25185. #define  DALTRK     0x0007          /* TRACK SPACE TYPE              */
  25186. #define  DALBLKLN   0x0009          /* BLOCK LENGTH                  */
  25187. #define  DALPRIME   0x000a          /* PRIMARY SPACE ALLOCATION      */
  25188. #define  DALSECND   0x000b          /* SECONDARY SPACE ALLOCATION    */
  25189. #define  DALDIR     0x000c          /* DIRECTORY BLOCK ALLOCATION    */
  25190. #define  DALSYSOU   0x0018          /* SYSOUT                        */
  25191. #define  DALSFMNO   0x001a          /* SYSOUT FORMS NUMBER           */
  25192. #define  DALCOPYS   0x001d          /* SYSOUT COPIES                 */
  25193. #define  DALUCS     0x0029          /* UNIVERSAL CHARACTER SET       */
  25194. #define  DALBLKSZ   0x0030          /* DCB BLOCKSIZE                 */
  25195. #define  DALDSORG   0x003c          /* DATA SET ORGANIZATION         */
  25196. #define  DALLRECL   0x0042          /* DCB LOGICAL RECORD LENGTH     */
  25197. #define  DALRECFM   0x0049          /* DCB RECORD FORMAT             */
  25198. #define  DALPERMA   0x0052          /* PERMANENTLY ALLOCATED ATTRIB  */
  25199. #define  DALRTDDN   0x0055          /* RETURN DDNAME                 */
  25200. #define  DALRTDSN   0x0056          /* RETURN DSNAME                 */
  25201. #define  DALRTORG   0x0057          /* RETURN D.S. ORGANIZATION      */
  25202. #define  DALSUSER   0x0058          /* SYSOUT REMOTE WORKSTATION     */
  25203. #define  DUNDDNAM   0x0001          /* DDNAME                        */
  25204. #define  DUNDSNAM   0x0002          /* DSNAME                        */
  25205. #define  DUNUNALC   0x0007          /* UNALLOC OPTION                */
  25206.  
  25207. #define  SHR        0x08
  25208. #define  NEW        0x04
  25209. #define  MOD        0x02
  25210. #define  OLD        0x01
  25211. #define  KEEP       0x08
  25212. #define  DELETE     0x04
  25213. #define  CATLG      0x02
  25214. #define  UNCATLG    0x01
  25215. #define  RECFM_F    0x80
  25216. #define  RECFM_V    0x40
  25217. #define  RECFM_U    0xc0
  25218. #define  RECFM_D    0x20
  25219. #define  RECFM_T    0x20
  25220. #define  RECFM_B    0x10
  25221. #define  RECFM_S    0x08
  25222. #define  RECFM_A    0x04
  25223. #define  RECFM_M    0x02
  25224. #define  RECFM_FB   (RECFM_F | RECFM_B)
  25225. #define  RECFM_VB   (RECFM_V | RECFM_B)
  25226. #define  DSORG_PS   0x4000
  25227. #define  DSORG_PO   0x0200
  25228.  
  25229. /************************ Newsgroup status ***************************/
  25230.  
  25231. #define NO_SUCH_GROUP             0x80
  25232. #define NEW_GROUP                 0x40
  25233. #define GROUP_FROM_NEWSRC         0x20
  25234. #define GROUP_LISTED              0x10
  25235. #define GROUP_SELECTED_UNREAD     0x08
  25236. #define GROUP_SELECTED_READ       0x04
  25237. #define GROUP_ERROR               0x02
  25238. #define GROUP_IN_TABLE            0x01
  25239.  
  25240. #define GROUP_SELECTED    (GROUP_SELECTED_UNREAD | GROUP_SELECTED_READ)
  25241.  
  25242. /* Note that the test GroupSelected means unread OR read, but the
  25243.  * assignment SetGroupSelected means set unread AND read selected
  25244.  * assignment OffGroupSelected means set unread AND read unselected.
  25245.  */
  25246.  
  25247. #define NoSuchGroup(X)            ((X)->status & NO_SUCH_GROUP)
  25248. #define NewGroup(X)               ((X)->status & NEW_GROUP)
  25249. #define GroupFromNewsrc(X)        ((X)->status & GROUP_FROM_NEWSRC)
  25250. #define GroupListed(X)            ((X)->status & GROUP_LISTED)
  25251. #define GroupSelectedUnread(X)    ((X)->status & GROUP_SELECTED_UNREAD)
  25252. #define GroupSelectedRead(X)      ((X)->status & GROUP_SELECTED_READ)
  25253. #define GroupError(X)             ((X)->status & GROUP_ERROR)
  25254. #define GroupInTable(X)           ((X)->status & GROUP_IN_TABLE)
  25255.  
  25256. #define GroupSelected(X)          ((X)->status & GROUP_SELECTED)
  25257.  
  25258. #define SetNoSuchGroup(X)          (X)->status |= NO_SUCH_GROUP
  25259. #define SetNewGroup(X)             (X)->status |= NEW_GROUP
  25260. #define SetGroupFromNewsrc(X)      (X)->status |= GROUP_FROM_NEWSRC
  25261. #define SetGroupListed(X)          (X)->status |= GROUP_LISTED
  25262. #define SetGroupSelectedUnread(X)  (X)->status |= GROUP_SELECTED_UNREAD
  25263. #define SetGroupSelectedRead(X)    (X)->status |= GROUP_SELECTED_READ
  25264. #define SetGroupError(X)           (X)->status |= GROUP_ERROR
  25265. #define SetGroupInTable(X)         (X)->status |= GROUP_IN_TABLE
  25266.  
  25267. #define SetGroupSelected(X)        (X)->status |= GROUP_SELECTED
  25268.  
  25269. #define OffNoSuchGroup(X)          (X)->status &= ~NO_SUCH_GROUP
  25270. #define OffNewGroup(X)             (X)->status &= ~NEW_GROUP
  25271. #define OffGroupFromNewsrc(X)      (X)->status &= ~GROUP_FROM_NEWSRC
  25272. #define OffGroupListed(X)          (X)->status &= ~GROUP_LISTED
  25273. #define OffGroupSelectedUnread(X)  (X)->status &= ~GROUP_SELECTED_UNREAD
  25274. #define OffGroupSelectedRead(X)    (X)->status &= ~GROUP_SELECTED_READ
  25275. #define OffGroupError(X)           (X)->status &= ~GROUP_ERROR
  25276. #define OffGroupInTable(X)         (X)->status &= ~GROUP_IN_TABLE
  25277.  
  25278. #define OffGroupSelected(X)        (X)->status &= ~GROUP_SELECTED
  25279.  
  25280. #define GroupListedOnly(X)        (GroupListed(X) && !GroupSelected(X))
  25281. #define GroupFromNNTP(X)          (GroupListed(X) || GroupSelected(X))
  25282. #define GroupFromNewsrcOnly(X)    (GroupFromNewsrc(X) && \
  25283.                                    !GroupListed(X) && \
  25284.                                    !GroupSelected(X))
  25285. #define BogusGroup(X)             (!GroupListed(X) && !GroupSelected(X))
  25286.  
  25287. #define ClearGroupStatus(X)        (X)->status = 0x00
  25288. #define NullGroupStatus(X)        ((X)->status == 0x00)
  25289.  
  25290. /************************* Article status ****************************/
  25291.  
  25292. #define NO_SUCH_ARTICLE           0x80
  25293. #define ARTICLE_ABSENT            0x40
  25294. #define ARTICLE_ERROR             0x20
  25295. #define ARTICLE_BAD_DATA          0x10
  25296. #define ARTICLE_HEAD_RETRIEVED    0x08
  25297. #define ARTICLE_BODY_RETRIEVED    0x04
  25298.  
  25299. #define ARTICLE_RETRIEVED         (ARTICLE_HEAD_RETRIEVED | \
  25300.                                    ARTICLE_BODY_RETRIEVED)
  25301.  
  25302. #define NoSuchArticle(X)          ((X)->status & NO_SUCH_ARTICLE)
  25303. #define ArticleAbsent(X)          ((X)->status & ARTICLE_ABSENT)
  25304. #define ArticleError(X)           ((X)->status & ARTICLE_ERROR)
  25305. #define ArticleBadData(X)         ((X)->status & ARTICLE_BAD_DATA)
  25306. #define ArticleHeadRetrieved(X)   ((X)->status & ARTICLE_HEAD_RETRIEVED)
  25307. #define ArticleBodyRetrieved(X)   ((X)->status & ARTICLE_BODY_RETRIEVED)
  25308.  
  25309. #define SetNoSuchArticle(X)        (X)->status |= NO_SUCH_ARTICLE
  25310. #define SetArticleAbsent(X)        (X)->status |= ARTICLE_ABSENT
  25311. #define SetArticleError(X)         (X)->status |= ARTICLE_ERROR
  25312. #define SetArticleBadData(X)       (X)->status |= ARTICLE_BAD_DATA
  25313. #define SetArticleHeadRetrieved(X) (X)->status |= ARTICLE_HEAD_RETRIEVED
  25314. #define SetArticleBodyRetrieved(X) (X)->status |= ARTICLE_BODY_RETRIEVED
  25315.  
  25316. #define OffNoSuchArticle(X)        (X)->status &=~NO_SUCH_ARTICLE
  25317. #define OffArticleAbsent(X)        (X)->status &=~ARTICLE_ABSENT
  25318. #define OffArticleError(X)         (X)->status &=~ARTICLE_ERROR
  25319. #define OffArticleBadData(X)       (X)->status &=~ARTICLE_BAD_DATA
  25320. #define OffArticleHeadRetrieved(X) (X)->status &=~ARTICLE_HEAD_RETRIEVED
  25321. #define OffArticleBodyRetrieved(X) (X)->status &=~ARTICLE_BODY_RETRIEVED
  25322.  
  25323. #define ArticleRetrieved(X)       ((X)->status & ARTICLE_RETRIEVED)
  25324. #define SetArticleRetrieved(X)     (X)->status |= ARTICLE_RETRIEVED
  25325. #define OffArticleRetrieved(X)     (X)->status &= ~ARTICLE_RETRIEVED
  25326.  
  25327. #define ClearArticleStatus(X)      (X)->status = 0x00
  25328. #define NullArticleStatus(X)      ((X)->status == 0x00)
  25329.  
  25330. /************************* Article vector ****************************/
  25331.  
  25332. /*
  25333.  * *** IMPORTANT! *** The hack of storing a vector of VARKs (which are
  25334.  * both pointers and status bits) depends on malloc() returning storage
  25335.  * for a struct on a doubleword boundary on MVS.  This allows us to
  25336.  * treat the low-order 3 bits of the pointer as trash so that we can
  25337.  * store status bits in it.  If this is not true, then this whole
  25338.  * technique will collapse like a house of cards, or else you should
  25339.  * stick a dummy double element into the newsarticle struct to make it
  25340.  * so.
  25341.  */
  25342.  
  25343. /*
  25344.  * Each article "pointer" (VARK) looks like this:
  25345.  *
  25346.  * -------------------------------------
  25347.  * |                       |   |   |   |
  25348.  * | pointer to article    | . | . | . |
  25349.  * |                       |   |   |   |
  25350.  * -------------------------------------
  25351.  *                           ^   ^   ^
  25352.  * where pointer is one of   |   |   |
  25353.  * NULL - no article         |   |   '--- 1 = Read, 0 = Unread
  25354.  * MISSING - article missing |   |   |
  25355.  * or the actual pointer     |   '------} 1 = Eligible, 0 = Ineligible
  25356.  *                           |
  25357.  *                           '----------} 1 = I know, 0 = I don't know
  25358.  *
  25359.  *                                        10 = Ineligible (not in table)
  25360.  *                                        11 = Eligible (in table)
  25361.  *                                        00 = Don't know yet
  25362.  *                                        01 cannot occur
  25363.  *
  25364.  */
  25365.  
  25366. #define  VARK                  unsigned int
  25367.  
  25368. #define  GETVARK(X,Y)          ((X)->article_vector\
  25369.                                 [(Y)-(X)->vector_first])
  25370. #define  GETVARKFIRST(X)       ((X)->article_vector[0])
  25371. #define  GETVARKLAST(X)        ((X)->article_vector\
  25372.                                 [(X)->article_vector_len-1])
  25373.  
  25374. #define  VARK2PARTICLE(X)      (struct newsarticle *) \
  25375.                                 (((unsigned int)(X)) & 0xfffffff8)
  25376. #define  VARK2NUMBER(X,Y)      (((Y)-(X)->article_vector) \
  25377.                                 + (X)->vector_first)
  25378. #define  VARK2BITS(X)          ((unsigned int)(X) & 0x00000007)
  25379. #define  VARK2READNESS(X)      ((unsigned int)(X) & 0x00000001)
  25380. #define  VARK2ELIGIBILITY(X)   ((unsigned int)(X) & 0x00000002)
  25381. #define  VARK2KNOWLEDGE(X)     ((unsigned int)(X) & 0x00000004)
  25382.  
  25383. #define  V_READNESS(X,Y)       VARK2READNESS(GETVARK(X,Y))
  25384. #define  V_ELIGIBILITY(X,Y)    VARK2ELIGIBILITY(GETVARK(X,Y))
  25385. #define  V_KNOWLEDGE(X,Y)      VARK2KNOWLEDGE(GETVARK(X,Y))
  25386.  
  25387. #define  V_NULL_ARTICLE        (struct newsarticle *)0
  25388. #define  V_MISSING_ARTICLE     (struct newsarticle *)np
  25389. #define  VARKMISSING           (unsigned int)np
  25390. #define  VARKNULL              (unsigned int)0
  25391.  
  25392. #define  V_UNREAD_BIT          0x00000000
  25393. #define  V_READ_BIT            0x00000001
  25394. #define  V_INELIGIBLE_BIT      0x00000000
  25395. #define  V_ELIGIBLE_BIT        0x00000002
  25396. #define  V_UNKNOWN_BIT         0x00000000
  25397. #define  V_KNOWN_BIT           0x00000004
  25398.  
  25399. #define  V_KNOWN_ELIGIBLE      (V_KNOWN_BIT + V_ELIGIBLE_BIT)
  25400. #define  V_KNOWN_INELIGIBLE    (V_KNOWN_BIT + V_INELIGIBLE_BIT)
  25401.  
  25402. #define  SetUnread(X)          X &= ~V_READ_BIT
  25403. #define  SetRead(X)            X |= V_READ_BIT
  25404. #define  SetNull(X)            X = VARKNULL
  25405.  
  25406.  /* Note that whenever you set something missing, you also set it
  25407.   * ineligible for table display.
  25408.   */
  25409.  
  25410. #define  SetMissing(X)         X = (VARK)\
  25411.                                    (VARKMISSING | \
  25412.                                     VARK2READNESS(X) | \
  25413.                                     V_KNOWN_INELIGIBLE)
  25414. #define  SetMissingUnread(X)   X = (VARK)\
  25415.                                    (VARKMISSING | \
  25416.                                     V_UNREAD_BIT | \
  25417.                                     V_KNOWN_INELIGIBLE)
  25418. #define  SetMissingRead(X)     X = (VARK)\
  25419.                                    (VARKMISSING | \
  25420.                                     V_READ_BIT | \
  25421.                                     V_KNOWN_INELIGIBLE)
  25422. #define  SetEligible(X)        X |= V_ELIGIBLE_BIT
  25423. #define  SetIneligible(X)      X &= ~V_ELIGIBLE_BIT
  25424. #define  SetKnown(X)           X |= V_KNOWN_BIT
  25425. #define  SetUnknown(X)         X &= ~V_KNOWN_BIT
  25426. #define  SetKnownEligible(X)   SetKnown(X), SetEligible(X)
  25427. #define  SetKnownIneligible(X) SetKnown(X), SetIneligible(X)
  25428.  
  25429. /* to get exact readness, use: VARK2READNESS(X) == V_whatever */
  25430.  
  25431. #define  IsRead(X)            ((X) & V_READ_BIT)
  25432. #define  IsUnread(X)          (!IsRead(X))
  25433. #define  IsEligible(X)        ((X) & V_ELIGIBLE_BIT)
  25434. #define  IsIneligible(X)      (!IsEligible(X))
  25435. #define  IsKnown(X)           ((X) & V_KNOWN_BIT)
  25436. #define  IsUnknown(X)         (!IsKnown(X))
  25437. #define  IsKnownEligible(X)   ((X)&V_KNOWN_ELIGIBLE==V_KNOWN_ELIGIBLE)
  25438. #define  IsKnownIneligible(X) ((X)&V_KNOWN_ELIGIBLE==V_KNOWN_INELIGIBLE)
  25439.  
  25440. #define  IsNull(X)            (VARK2PARTICLE(X) == V_NULL_ARTICLE)
  25441. #define  IsMissing(X)         (VARK2PARTICLE(X) == V_MISSING_ARTICLE)
  25442. #define  IsPresent(X)         (!IsMissing(X))
  25443. #define  IsMissingUnread(X)   (IsMissing(X) && IsUnread(X))
  25444. #define  IsMissingRead(X)     (IsMissing(X) && IsRead(X))
  25445. #define  IsPresentUnread(X)   (IsPresent(X) && IsUnread(X))
  25446. #define  IsPresentRead(X)     (IsPresent(X) && IsRead(X))
  25447.  
  25448. #define  NOTIFY_MSG   1
  25449. #define  WARNING_MSG  2
  25450. #define  CRITICAL_MSG 3
  25451.  
  25452. #define  WARN1(X)           NNMpmsg(np,NOTIFY_MSG,NULL,X)
  25453. #define  WARN2(X,Y)         NNMpmsg(np,NOTIFY_MSG,NULL,X,Y)
  25454. #define  WARN3(X,Y,Z)       NNMpmsg(np,NOTIFY_MSG,NULL,X,Y,Z)
  25455. #define  WARN4(X,Y,Z,W)     NNMpmsg(np,NOTIFY_MSG,NULL,X,Y,Z,W)
  25456. #define  ERR1(X)            NNMpmsg(np,WARNING_MSG,NULL,X)
  25457. #define  ERR2(X,Y)          NNMpmsg(np,WARNING_MSG,NULL,X,Y)
  25458. #define  ERR3(X,Y,Z)        NNMpmsg(np,WARNING_MSG,NULL,X,Y,Z)
  25459. #define  ERR4(X,Y,Z,W)      NNMpmsg(np,WARNING_MSG,NULL,X,Y,Z,W)
  25460. #define  CRIT1(X)           NNMpmsg(np,CRITICAL_MSG,NULL,X)
  25461. #define  CRIT2(X,Y)         NNMpmsg(np,CRITICAL_MSG,NULL,X,Y)
  25462. #define  CRIT3(X,Y,Z)       NNMpmsg(np,CRITICAL_MSG,NULL,X,Y,Z)
  25463.  
  25464. #define  MSG(X)             (MSG_is_obsolete,)
  25465.  
  25466. #define  GETMAIN(Ptr,Typ,Siz,For) \
  25467.          NNMgetm(np,(char **)&(Ptr),(sizeof(Typ))*(Siz),For)
  25468.  
  25469. #define  FREEMAIN(Ptr,For)    if (Ptr) {NNMfreem(np,(char *)Ptr,For);}
  25470.  
  25471. /****** Data and structure definitions. ******************************/
  25472.  
  25473. enum scroll         {NO_SCROLL, UP, DOWN, LEFT, RIGHT, LOCATE};
  25474. enum extreq         {EXTRACT_IT, PRINT_IT};
  25475. enum data_set_type  {PDS, SEQ, UNK, JES};
  25476. enum list_option    {LIST_ALL, LIST_NEW, LIST_ALL_DISCONNECT};
  25477. enum choose_reason  {RETRIEVE, MARK_ONLY};
  25478.  
  25479. enum socket_retval  {
  25480.                      SERVER_READ_OK,
  25481.                      SERVER_READ_ERROR,
  25482.                      SERVER_BUFFER_ERROR,
  25483.                      SERVER_NO_MORE
  25484.                     };
  25485.  
  25486. enum display_retval {
  25487.                      DISPLAY_REPEAT,
  25488.                      DISPLAY_EXIT,
  25489.                      DISPLAY_ERROR,
  25490.                      DISPLAY_FAILURE
  25491.                     };
  25492.  
  25493.  
  25494.  
  25495. enum user_option    {
  25496.                      OPTION_ALL,
  25497.                      OPTION_HEADER,
  25498.                      OPTION_OTHER,
  25499.                      OPTION_VIEW
  25500.                     };
  25501.  
  25502. enum article_cookie {
  25503.                      NULL_ARTICLE_COOKIE  ,
  25504.                      UNREAD_THIS_ARTICLE  ,
  25505.                      NEXT_ARTICLE         ,
  25506.                      PREV_ARTICLE         ,
  25507.                      NEXT_TABLED_ARTICLE  ,
  25508.                      PREV_TABLED_ARTICLE  ,
  25509.                      NEXT_UNREAD_ARTICLE  ,
  25510.                      PREV_UNREAD_ARTICLE  ,
  25511.                      NEXT_THREAD_ARTICLE  ,
  25512.                      PREV_THREAD_ARTICLE  ,
  25513.                      FIRST_THREAD_ARTICLE ,
  25514.                      LAST_THREAD_ARTICLE  ,
  25515.                      NEW_THREAD_ARTICLE   ,
  25516.                      REDISPLAY_ARTICLE
  25517.                     };
  25518.  
  25519. typedef  struct   _textunit     TEXTUNIT;
  25520. typedef  unsigned int           IPADDRESS;
  25521. typedef  enum     scroll        SCROLL;
  25522. typedef  enum     extreq        EXTREQ;
  25523.  
  25524. struct textline    {
  25525.                     struct textline    *next;
  25526.                     short               text_length;
  25527.                     short               tab_expanded_text_length;
  25528.                     char               *tab_expanded_text;
  25529.                     char                text[1];  /* dummy */
  25530.                    };
  25531.  
  25532. struct texthdr     {
  25533.                     int                   text_line_count;
  25534.                     short                 text_max_length;
  25535.                     short                 text_max_tab_expanded_length;
  25536.                     struct textline      *text_body_line;
  25537.                     struct textline      *first_text_line;
  25538.                     struct textline      *current_text_line;
  25539.                     struct textline      *last_text_line;
  25540.                    };
  25541.  
  25542. /* see note on newsarticle struct under article vector stuff */
  25543.  
  25544. struct newsarticle {
  25545.                     char                 *from;
  25546.                     char                 *subject;
  25547.                     char                 *date;
  25548.                     char                 *message_id;
  25549.                     char                 *csubject;
  25550.                     int                   number;
  25551.                     char                  action;
  25552.                     char                  status;
  25553.                     struct texthdr        thdr;
  25554.                    };
  25555.  
  25556. struct newsgroup   {
  25557.                     struct newsgroup     *next;
  25558.                     struct newsgroup     *next2;
  25559.                     struct newsgroup     *next3;
  25560.                     char                 *saved_newsrc_line;
  25561.                     VARK                 *article_vector;
  25562.                     VARK                **sort_vector;
  25563.                     int                   low_number;
  25564.                     int                   high_number;
  25565.                     int                   vector_first;
  25566.                     int                   vector_last;
  25567.                     int                   article_count;
  25568.                     int                   unread_count;
  25569.                     int                   sort_count;
  25570.                     int                   article_vector_len;
  25571.                     int                   registered;
  25572.                     char                  status;
  25573.                     char                  saved_newsrc_data [12];
  25574.                     char                  name [1]; /* dummy len */
  25575.                    };
  25576.  
  25577. struct cmddesc   {
  25578.                   char    command_name[COMMANDSIZE];
  25579.                   Bool    (*command_processor)();
  25580.                  };
  25581.  
  25582. struct seldesc   {
  25583.                   char    selection_code;
  25584.                   Bool    (*selection_processor)();
  25585.                  };
  25586.  
  25587. struct tabledesc {
  25588.                   char   *command_variable;
  25589.         struct cmddesc   *first_cmddesc;
  25590.         struct seldesc   *first_seldesc;
  25591.         struct cmddesc   *next_cmddesc;
  25592.                  };
  25593.  
  25594. struct tablevector {
  25595.                     struct tabledesc *newsgroup_display_table;
  25596.                     struct tabledesc *article_display_table;
  25597.                     struct tabledesc *text_display_table;
  25598.                    };
  25599.  
  25600. struct _textunit {
  25601.                   unsigned short         key;
  25602.                   unsigned short         num;
  25603.                   struct {
  25604.                           unsigned short len;
  25605.                           char           prm[80];
  25606.                          }               ent;
  25607.                  };
  25608.  
  25609. struct extraction {
  25610.                    int                   from_article_number;
  25611.                    int                   to_article_number;
  25612.                    int                   article_count;
  25613.                    enum data_set_type    mode;
  25614.                    void                (*closer)();
  25615.                    Bool                  appending;
  25616.                    Bool                  blanking;
  25617.                    Bool                  tab_expanding;
  25618.                    Bool                  ejecting;
  25619.                    Bool                  formfeeding;
  25620.                    char                  panelname     [9];
  25621.                    char                  dsname       [65];
  25622.                    char                  separator    [81];
  25623.                    char                  member_prefix [9];
  25624.                    char                  ddname        [9];
  25625.                    char                  member        [9];
  25626.                   };
  25627.  
  25628. struct countdown  {
  25629.                    Bool                  do_update;
  25630.                    int                   done;
  25631.                    int                   to_do;
  25632.                   };
  25633.  
  25634. struct nncb {
  25635.              char    *server_buf;
  25636.              char    *client_buf;
  25637.              char    *nntp_command;
  25638.              char    *nntp_message_text;
  25639.              char    *extract_separator_line;
  25640.  struct newsgroup    *first_newsgroup;
  25641.  struct newsgroup    *current_newsgroup;
  25642.  struct newsgroup    *last_newsgroup;
  25643.  struct newsgroup    *first_newsgroup_alt;
  25644.  struct newsgroup    *last_added_newsgroup;
  25645.  struct tablevector  *display_table_vector;
  25646.  struct extraction   *extractionp;
  25647.              FILE    *debug_file;
  25648.              FILE    *newsrc_file;
  25649.              FILE    *extract_file;
  25650.              FILE    *batch_infile;
  25651.              FILE    *batch_outfile;
  25652.              void    *batch_hook;
  25653. #ifdef FETCH
  25654.               int   (*isplink_pointer)();
  25655.               int   (*ispexec_pointer)();
  25656. #endif
  25657.   struct newsarticle *article_being_viewed;
  25658.               VARK  **top_sorted_article;
  25659.               VARK  **current_sortvark;
  25660.               int     top_article;
  25661.               int     ispfrc;
  25662.               int     nntp_message_num;
  25663.               int     socknum;
  25664.               int     g_bytes_returned;
  25665.               int     g_buf_index;
  25666.               int     new_newsgroup_count;
  25667.               int     article_rows;
  25668.               int     updatefreq;      /* ddi */
  25669.               int     text_find_left_bound;
  25670.               int     text_find_right_bound;
  25671.  enum article_cookie  another_article;
  25672.    struct texthdr     thdr;
  25673.         IPADDRESS     client_ip_address;
  25674.         IPADDRESS     server_ip_address;
  25675.              time_t   lasttime;           /* ddi */
  25676.              time_t   firstime;           /* ddi */
  25677.              Bool     test_mode;
  25678.              Bool     debug_mode;
  25679.              Bool     batch_mode;
  25680.              Bool     quit;
  25681.              Bool     time_to_go_home;
  25682.              Bool     server_has_something_pending;
  25683.              Bool     server_finished_replying;
  25684.              Bool     sending_text;
  25685.              Bool     receiving_text;
  25686.              Bool     something_to_print;
  25687.              Bool     dont_read;
  25688.              Bool     connected_to_server;
  25689.              Bool     connection_broken;
  25690.              Bool     closing_connection;
  25691.              Bool     reconnect_in_progress;
  25692.              Bool     posting_allowed;
  25693.              Bool     newsgroup_selected;
  25694.              Bool     newsgroup_not_found;
  25695.              Bool     newsgroup_order_changed;
  25696.              Bool     brand_new_newsrc;
  25697.              Bool     newsgroup_criterion_changed;
  25698.              Bool     show_all_newsgroups;
  25699.              Bool     following_up;
  25700.              Bool     extract_tab_expanding;
  25701.              Bool     extract_appending;
  25702.              Bool     extract_blank_before_separator;
  25703.              Bool     extract_ejecting;
  25704.              Bool     extract_formfeeding;
  25705.              Bool     extract_write_error;
  25706.              Bool     extract_close_error;
  25707.              Bool     please_locate_group;
  25708.              Bool     please_find_group;
  25709.              Bool     repeat_find;
  25710.              Bool     article_criterion_changed;
  25711.              Bool     article_repeat_find;
  25712.              Bool     article_text_not_found;
  25713.              Bool     warn_overwrite;
  25714.              Bool     warn_append;
  25715.              Bool     dont_reissue_socket_command;
  25716.              Bool     show_all_articles;
  25717.              Bool     update_adding_newsgroups;
  25718.              Bool     update_rewriting_newsrc;
  25719.              Bool     update_retrieving_articles;
  25720.              Bool     bypass_header_retrieval;
  25721.              Bool     unread_articles_only;
  25722.              Bool     setmsg;
  25723.              Bool     newsgroup_autoscroll;
  25724.              Bool     article_autoscroll;
  25725.              Bool     sort_by_subject;
  25726.              Bool     xhdr_not_available;
  25727.              Bool     newsgroup_autocursor;
  25728.              Bool     article_autocursor;
  25729.              Bool     setcursor;
  25730.              Bool     printing;
  25731.              Bool     dont_reconnect;
  25732.              char     newsgroup_order;
  25733.              char     newsgroup_find_option;
  25734.              char     article_find_option;
  25735.              char     preselection;
  25736.              char     barchar;                /* ddi */
  25737.              char     text_dispchar;
  25738.              char     text_find_what;
  25739.              char     text_find_type;
  25740.              char     text_find_trans;
  25741.              char     newsrc_to_open          [ 12];
  25742.              char     nnrfcopt                [  2];
  25743.              char     nnrfcinc                [256];
  25744.              char     nnrfcexc                [256];
  25745.              char     maildsn                 [ 64];
  25746.              char     messageid               [128];
  25747.              char     nnregnng                [  9];
  25748.              char     nngroup                 [GROUP_NAME_SIZE+1];
  25749.              char     nnserver                [MAXHOSTNAMELEN+1];
  25750.              char     nnclient                [MAXHOSTNAMELEN+1];
  25751.              char     client_hostname         [MAXHOSTNAMELEN+1];
  25752.              char     client_ip_addrstr       [16];
  25753.              char     server_hostname         [MAXHOSTNAMELEN+1];
  25754.              char     server_ip_addrstr       [16];
  25755.              char     g_buf                   [READ_BYTES];
  25756.              char     newsgroup_locate_string [GROUP_NAME_SIZE+1];
  25757.              char     newsgroup_only_string   [GROUP_NAME_SIZE+1];
  25758.              char     newsgroup_find_string   [GROUP_NAME_SIZE+1];
  25759.              char     article_only_string     [GROUP_NAME_SIZE+1];
  25760.              char     article_find_string     [GROUP_NAME_SIZE+1];
  25761.              char     lastNGdate              [7];      /* ddi */
  25762.              char     lastNGtime              [7];      /* ddi */
  25763.              char     selsubj                 [81];     /* ddi */
  25764.              char     text_find_string        [GROUP_NAME_SIZE+1];
  25765.             };
  25766.  
  25767. #ifdef MVS
  25768. #ifndef I370
  25769. extern char                 ebcdictoascii[];
  25770. extern char                 asciitoebcdic[];
  25771. #endif
  25772. #endif
  25773.  
  25774. #ifndef FETCH
  25775. extern int                  isplink();
  25776. extern int                  ispexec();
  25777. #endif
  25778.  
  25779. /****** Procedure and function declarations. *************************/
  25780.  
  25781. extern struct newsgroup   *NNMaddng(struct nncb *, char *);
  25782. extern void                NNMadjua(struct nncb *, struct newsgroup *,
  25783.                                                         int, int, int);
  25784. extern void                NNMallav(struct nncb *, struct newsgroup *,
  25785.                                                              int, int);
  25786. extern Bool                NNMalloc(char *, char *, enum data_set_type,
  25787.                                                                   int);
  25788. extern Bool                NNMauth (struct nncb *);
  25789. extern int                 NNMbatch(struct nncb *);
  25790. extern void                NNMbtext(struct nncb *, struct texthdr *,
  25791.                                                                FILE *);
  25792. extern Bool                NNMcar  (struct nncb *,struct newsgroup *,
  25793.                                        int,VARK *,struct newsarticle **,
  25794.                                        struct countdown *,
  25795.                                        enum choose_reason);
  25796. extern void                NNMclrng(struct nncb *);
  25797. extern void                NNMclrtx(struct nncb *,struct newsarticle *);
  25798. extern void                NNMcnrf (struct nncb *, char *, Fool);
  25799. extern Bool                NNMconn (struct nncb *);
  25800. extern char               *NNMcopy (struct nncb *, char *);
  25801. extern Bool                NNMdcan (struct nncb *,struct newsgroup *,
  25802.                                                   struct newsarticle *);
  25803. extern void                NNMdfail(int,__S99parms *);
  25804. extern void                NNMdisc (struct nncb *);
  25805. extern int                 NNMdispl(struct nncb *, char *);
  25806. extern Bool                NNMdlang(struct nncb *, enum list_option);
  25807. extern void                NNMdmail(struct nncb *,struct newsgroup *,
  25808.                                                   struct newsarticle *);
  25809. extern enum display_retval NNMdmenu(struct nncb *, Bool (**)());
  25810. extern struct newsgroup   *NNMdng  (struct nncb *,
  25811.                                            struct newsgroup *, char *);
  25812. extern void                NNMdnntp(struct nncb *, char *);
  25813. extern void                NNMdoit (struct nncb *,
  25814.                                             struct newsarticle *, Fool);
  25815. extern void                NNMdpost(struct nncb *,struct newsgroup *,
  25816.                                                   struct newsarticle *);
  25817. extern void                NNMdsopt(struct nncb *,char *);
  25818. extern void                NNMdump (struct nncb *,char *, char *, int);
  25819. extern void                NNMesrvr(struct nncb *);
  25820. extern Bool                NNMestng(struct nncb *, char *);
  25821. extern void                NNMfreem(struct nncb *,char *,char *);
  25822. extern FILE               *NNMgetds(struct nncb *,struct extraction *);
  25823. extern void                NNMgetm (struct nncb *,char **,int,char *);
  25824. extern Bool                NNMgsrvl(struct nncb *, char **);
  25825. extern void                NNMierr (struct nncb *);
  25826. extern int                 NNMiget (struct nncb *, char *);
  25827. extern void                NNMimsg (struct nncb *, char *);
  25828. extern void                NNMinit (struct nncb *);
  25829. extern Bool                NNMispf (struct nncb *, char *);
  25830. extern Bool                NNMivget(struct nncb *, char *, char *,int);
  25831. extern Bool                NNMivput(struct nncb *, char *, char *,int);
  25832. extern void                NNMmarr(struct nncb *, struct newsgroup *,
  25833.                                                                 VARK *);
  25834. extern void                NNMmaru(struct nncb *, struct newsgroup *,
  25835.                                                                 VARK *);
  25836. extern void                NNMnntp (struct nncb *);
  25837. extern void                NNMonrf (struct nncb *, char *);
  25838. extern struct textline    *NNMouttx(struct nncb *, char *,
  25839.                                                   struct newsarticle *);
  25840. extern Bool                NNMpick (struct nncb *,struct newsarticle *);
  25841. extern Bool                NNMpng  (struct nncb *,struct newsgroup *,
  25842.                                                              Fool,Fool);
  25843. extern Bool                NNMqar  (struct nncb *,struct newsarticle *);
  25844. extern void                NNMqng  (struct nncb *,struct newsgroup *);
  25845. extern struct newsarticle *NNMrarh (struct nncb *,struct newsgroup *,
  25846.                                          VARK *,int,struct countdown *);
  25847. extern int                 NNMrart (struct nncb *,struct newsgroup *,
  25848.                                                              Fool,Fool);
  25849. extern void                NNMrbfm (struct nncb *);
  25850. extern Bool                NNMrecon(struct nncb *);
  25851. extern void                NNMrperr(struct nncb *);
  25852. extern Bool                NNMsave (struct nncb *,char *);
  25853. extern Bool                NNMsockt(struct nncb *);
  25854. extern void                NNMsopt (struct nncb *, enum user_option);
  25855. extern Bool                NNMsort (struct nncb *,struct newsgroup *);
  25856. extern void                NNMssrvr(struct nncb *);
  25857. extern char               *NNMstrlc(char *, char *);
  25858. extern Bool                NNMsumat(char *, char *);
  25859. extern int                 NNMtso  (char *);
  25860. extern Bool                NNMunalc(char *);
  25861. extern void                NNMupdt (struct nncb *,struct countdown *,
  25862.                                                   char *);
  25863. extern Bool                NNMvar  (struct nncb *,struct newsgroup *);
  25864. extern void                NNMview (struct nncb *,struct newsgroup *,
  25865.                                                   struct newsarticle *,
  25866.                                                   struct texthdr *,
  25867.                                                   char *);
  25868. extern Bool                NNMvng  (struct nncb *);
  25869. extern void                NNMvtx  (struct nncb *,struct newsgroup *,
  25870.                                                   struct newsarticle *);
  25871. extern Bool                NNMxartt(struct nncb *,struct newsgroup *,
  25872.                                                   enum data_set_type);
  25873. extern Bool                NNMxartx(struct nncb *,struct newsgroup *,
  25874.                                                   enum data_set_type);
  25875. extern Bool                NNMxlist(struct nncb *,enum data_set_type);
  25876. extern Bool                NNMxtx  (struct nncb *,struct newsarticle *,
  25877.                                                   Fool);
  25878.  
  25879. #ifndef SUPPRESS_V_DECLARATION
  25880. extern void                NNMpmsg (struct nncb *,int,char *,char *,
  25881.                                                                   ...);
  25882. #endif
  25883.  
  25884. #ifdef C370V2
  25885. #pragma checkout(resume)
  25886. #endif
  25887.  
  25888. ./   ADD NAME=NNBATCH,SSI=01010007
  25889.  
  25890.  /********************************************************************/
  25891.  /*                                                                  */
  25892.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  25893.  /*                                                                  */
  25894.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  25895.  /* including the implied warranties of merchantability and fitness, */
  25896.  /* are expressly denied.                                            */
  25897.  /*                                                                  */
  25898.  /* Provided this copyright notice is included, this software may    */
  25899.  /* be freely distributed and not offered for sale.                  */
  25900.  /*                                                                  */
  25901.  /* Changes or modifications may be made and used only by the maker  */
  25902.  /* of same, and not further distributed.  Such modifications should */
  25903.  /* be mailed to the author for consideration for addition to the    */
  25904.  /* software and incorporation in subsequent releases.               */
  25905.  /*                                                                  */
  25906.  /********************************************************************/
  25907.  
  25908. /* ------------------ "nnbatch.h" include member ------------------- */
  25909.  
  25910. /* Include file for NNMVS batch mode operations. */
  25911.  
  25912.  
  25913. #define FIRST_ARTICLE_IN_RANGE             (-1)
  25914. #define LAST_ARTICLE_IN_RANGE              (2147483647)
  25915.  
  25916. #define MIN_RESERVED_WORD_LENGTH 2
  25917. #define MAX_RESERVED_WORD_LENGTH 10
  25918.  
  25919. #define ANYTYPE     void *
  25920.  
  25921. #define PEEK()      (NNMbgtok(np,bp,TOKEN_PEEK) ? &bp->nextok : NULL)
  25922. #define EAT()       (void)NNMbgtok(np,bp,TOKEN_READ)
  25923.  
  25924. #define SETA(X,Y)   NNMbvput(np,bp,(X),NUMBER_SYMTYPE,(ANYTYPE)(Y))
  25925. #define SETB(X,Y)   NNMbvput(np,bp,(X),FLAG_SYMTYPE,  (ANYTYPE)(Y))
  25926. #define SETC(X,Y)   NNMbvput(np,bp,(X),STRING_SYMTYPE,(ANYTYPE)(Y))
  25927.  
  25928. #define GETA(X)     (int)   NNMbvget(np,bp,(X),NUMBER_SYMTYPE)
  25929. #define GETB(X)     (Fool)  NNMbvget(np,bp,(X),FLAG_SYMTYPE)
  25930. #define GETC(X)     (char *)NNMbvget(np,bp,(X),STRING_SYMTYPE)
  25931.  
  25932. typedef struct newscmd *(*CommandParser)   ();
  25933. typedef void            (*CommandExecutor) ();
  25934.  
  25935. enum tokentype        {NO_TOKEN,
  25936.                        EOL_TOKEN,
  25937.                        EOF_TOKEN,
  25938.                        AND_TOKEN,
  25939.                        OR_TOKEN,
  25940.                        NOT_TOKEN,
  25941.                        GT_TOKEN,
  25942.                        LT_TOKEN,
  25943.                        EQ_TOKEN,
  25944.                        NE_TOKEN,
  25945.                        GE_TOKEN,
  25946.                        LE_TOKEN,
  25947.                        LPAR_TOKEN,
  25948.                        RPAR_TOKEN,
  25949.                        PLUS_TOKEN,
  25950.                        MINUS_TOKEN,
  25951.                        TIMES_TOKEN,
  25952.                        OVER_TOKEN,
  25953.                        SEMI_TOKEN,
  25954.                        WORD_TOKEN,
  25955.                        NUMBER_TOKEN,
  25956.                        STRING_TOKEN,
  25957.                        ERROR_TOKEN
  25958.                       };
  25959.  
  25960. enum tokenfunc        {
  25961.                        TOKEN_PEEK,
  25962.                        TOKEN_READ,
  25963.                        TOKEN_FLUSH
  25964.                       };
  25965.  
  25966. enum batchmode        {
  25967.                        INITIAL_MODE,
  25968.                        PER_NEWSGROUP_MODE,
  25969.                        PER_ARTICLE_MODE,
  25970.                        TEXT_MODE,
  25971.                        ERROR_MODE,
  25972.                        ANY_MODE
  25973.                       };
  25974.  
  25975. enum marking_mode     {
  25976.                        MARKING_READ,
  25977.                        MARKING_UNREAD
  25978.                       };
  25979.  
  25980. enum extracting_mode  {
  25981.                        NO_EXTRACTING_MODE,
  25982.                        EXTRACTING_ALL,
  25983.                        EXTRACTING_READ,
  25984.                        EXTRACTING_UNREAD
  25985.                       };
  25986.  
  25987. enum which_newsgroups {
  25988.                        NO_NEWSGROUPS,
  25989.                        ALL_NEWSGROUPS,
  25990.                        REGISTERED_NEWSGROUPS,
  25991.                        UNREGISTERED_NEWSGROUPS,
  25992.                        NAMED_NEWSGROUPS,
  25993.                        MASKED_NEWSGROUPS
  25994.                       };
  25995.  
  25996. enum which_articles   {
  25997.                        NO_ARTICLES,
  25998.                        ALL_ARTICLES,
  25999.                        READ_ARTICLES,
  26000.                        UNREAD_ARTICLES,
  26001.                        RANGED_ARTICLES
  26002.                       };
  26003.  
  26004. enum symtype          {
  26005.                        NO_SYMTYPE,
  26006.                        STRING_SYMTYPE,
  26007.                        NUMBER_SYMTYPE,
  26008.                        FLAG_SYMTYPE
  26009.                       };
  26010.  
  26011. /*-------------------------------------------------------------------*
  26012.  * Define structures to handle expressions computed at run time.
  26013.  *-------------------------------------------------------------------*/
  26014.  
  26015. #include "nnptree.h"   /* Grammar to handle general expressions */
  26016.  
  26017. /*-------------------------------------------------------------------*
  26018.  * newsgroup_crit: defines criteria for selecting newsgroups.
  26019.  *                 Corresponds to xxx in:
  26020.  *                   FOR xxx WHEN (yyy) DO zzz
  26021.  *                 in top-level mode.
  26022.  *-------------------------------------------------------------------*/
  26023.  
  26024. struct newsgroup_crit {
  26025.                        enum which_newsgroups     which;
  26026.                        struct ptree             *groups;
  26027.                       };
  26028.  
  26029. /*-------------------------------------------------------------------*
  26030.  * article_crit: defines criteria for selecting articles.
  26031.  *               Corresponds to xxx in:
  26032.  *                 FOR xxx WHEN (yyy) DO zzz
  26033.  *               in per-newsgroup mode.
  26034.  *-------------------------------------------------------------------*/
  26035.  
  26036. struct article_crit {
  26037.                        enum which_articles       which;
  26038.                        struct ptree             *first;
  26039.                        struct ptree             *last;
  26040.                       };
  26041.  
  26042. /*-------------------------------------------------------------------*
  26043.  * for_newsgroups: defines what to do for each newsgroup and which
  26044.  *                 newsgroups were selected.  Corresponds to:
  26045.  *                   FOR xxx WHEN (yyy) DO zzz
  26046.  *                 in top-level mode.
  26047.  *-------------------------------------------------------------------*/
  26048.  
  26049. struct for_newsgroups {
  26050.                        struct ptree             *filter;
  26051.                        struct newsgroup_crit     crit;
  26052.                        struct cmdtree           *treep;
  26053.                       };
  26054.  
  26055. /*-------------------------------------------------------------------*
  26056.  * for_articles:   defines what to do for each article and which
  26057.  *                 articles were selected.  Corresponds to:
  26058.  *                   FOR xxx WHEN (yyy) DO zzz
  26059.  *                 in per-newsgroup mode.
  26060.  *-------------------------------------------------------------------*/
  26061.  
  26062. struct for_articles   {
  26063.                        struct ptree             *filter;
  26064.                        struct article_crit       crit;
  26065.                        struct cmdtree           *treep;
  26066.                       };
  26067.  
  26068. /*-------------------------------------------------------------------*
  26069.  * OK, here are defined the kinds of commands.
  26070.  *-------------------------------------------------------------------*/
  26071.  
  26072. struct initial_mode_cmd        {
  26073.                                 struct for_newsgroups       fors;
  26074.                                };
  26075.  
  26076. struct per_newsgroup_mode_cmd  {
  26077.                                 struct for_articles         fors;
  26078.                                };
  26079.  
  26080. struct if_cmd                  {
  26081.                                 struct ptree               *condition;
  26082.                                 struct cmdtree             *thencmds;
  26083.                                 struct cmdtree             *elsecmds;
  26084.                                };
  26085.  
  26086. struct set_cmd                 {
  26087.                                 struct ptree               *ptreep;
  26088.                                 char *                      set_symbol;
  26089.                                 enum symtype                set_type;
  26090.                                };
  26091.  
  26092. struct mark_cmd                {
  26093.                                 enum marking_mode           marking;
  26094.                                };
  26095.  
  26096. struct extract_cmd             {
  26097.                                 enum extracting_mode        extracting;
  26098.                                };
  26099.  
  26100. struct miscellaneous_cmd       {
  26101.                                 struct ptree               *ptreep;
  26102.                                };
  26103.  
  26104. union some_mode_cmd   {
  26105.                        struct initial_mode_cmd       icmd;
  26106.                        struct per_newsgroup_mode_cmd ncmd;
  26107.                        struct if_cmd                 fcmd;
  26108.                        struct set_cmd                scmd;
  26109.                        struct mark_cmd               rcmd;
  26110.                        struct extract_cmd            xcmd;
  26111.                        struct miscellaneous_cmd      mcmd;
  26112.                       };
  26113.  
  26114. /*-------------------------------------------------------------------*
  26115.  * newscmd:   defines format of operations to perform on something.
  26116.  *-------------------------------------------------------------------*/
  26117.  
  26118. struct newscmd        {
  26119.                        enum batchmode            mode;
  26120.                        CommandExecutor           proc;
  26121.                        union some_mode_cmd       cmd;
  26122.                       };
  26123.  
  26124. struct cmdtree        {
  26125.                        struct cmdtree *next;
  26126.                        struct newscmd *cmd;
  26127.                       };
  26128.  
  26129. #define MAX_SYMBOL_LENGTH      16
  26130.  
  26131. /*-------------------------------------------------------------------*
  26132.  * symtab:    defines symbol table that holds values of variables.
  26133.  *            The complete symbol table is a classic binary tree of
  26134.  *            symtab structs.
  26135.  *
  26136.  * To allocate, take length of variable value string,
  26137.  * then add that to offsetof(struct symtab,symval) to get total.
  26138.  *-------------------------------------------------------------------*/
  26139.  
  26140. struct symtab {
  26141.                char            symvar[MAX_SYMBOL_LENGTH];
  26142.                struct symtab  *left;
  26143.                struct symtab  *right;
  26144.                enum symtype    type;
  26145.                int             symnum;
  26146.                int             vallen;
  26147.                char            symval[1];      /* dummy for alloc */
  26148.               };
  26149.  
  26150. struct token {
  26151.               enum tokentype   type;
  26152.               char             string [260];
  26153.               int              number;
  26154.              };
  26155.  
  26156. struct batch {
  26157.               struct cmdtree     *treetop;
  26158.               struct cmdtree     *treebottom;
  26159.               struct symtab      *symtabp;
  26160.               struct newsgroup   *gp;
  26161.               VARK               *vp;
  26162.               struct newscmd     *ifcmd;
  26163.               char               *inchar;
  26164.               char               *reserved_words;
  26165.               char               *outfilename;
  26166.               FILE               *outfp;
  26167.               int                 input_errors;
  26168.               int                 request_errors;
  26169.               enum batchmode      mode;
  26170.               enum data_set_type  extractds_mode;
  26171.               CommandParser       endproc;
  26172.               jmp_buf             jump;
  26173.               struct token        curtok;
  26174.               struct token        nextok;
  26175.               Bool                exactcase;
  26176.               Bool                syntax_error;
  26177.               Bool                runtime_error;
  26178.               Bool                eof;
  26179.               Bool                quit;
  26180.               Bool                stop_at_newline;
  26181.               Bool                tokens_read;
  26182.               Bool                newsgroups_retrieved;
  26183.               char                inline          [260];
  26184.               char                extractds        [81];
  26185.               char                extractds_part1  [81];
  26186.               char                extractds_part2  [81];
  26187.               char                extractds_member [81];
  26188.              };
  26189.  
  26190. extern ANYTYPE         NNMbbexp(struct nncb *, struct batch *,
  26191.                                           struct ptree *,enum symtype);
  26192. extern Bool            NNMbconn(struct nncb *, struct batch *);
  26193. extern struct symtab  *NNMbdecl(struct nncb *, struct batch *, char *,
  26194.                                                 enum symtype, ANYTYPE);
  26195. extern void            NNMbflus(struct nncb *, struct batch *);
  26196. extern CommandParser   NNMbgcmd(struct nncb *, struct batch *);
  26197. extern struct cmdtree *NNMbgdo (struct nncb *, struct batch *,
  26198.                                                        enum batchmode);
  26199. extern struct ptree   *NNMbgexp(struct nncb *, struct batch *,
  26200.                                                          enum symtype);
  26201. extern Bool            NNMbgtok(struct nncb *, struct batch *,
  26202.                                                        enum tokenfunc);
  26203. extern FILE           *NNMbsout(struct nncb *, struct batch *);
  26204. extern void            NNMbsynt(struct nncb *, struct batch *,
  26205.                                                   char *, int, char *);
  26206. extern void            NNMbtras(struct nncb *, struct batch *, char *);
  26207. extern ANYTYPE         NNMbvget(struct nncb *, struct batch *, char *,
  26208.                                                          enum symtype);
  26209. extern void            NNMbvput(struct nncb *, struct batch *, char *,
  26210.                                                 enum symtype, ANYTYPE);
  26211. extern void            NNMbxfar (struct nncb *, struct batch *,
  26212.                                                       struct newscmd *);
  26213. extern void            NNMbxfng (struct nncb *, struct batch *,
  26214.                                                       struct newscmd *);
  26215.  
  26216. ./   ADD NAME=NNPTREE,SSI=01000033
  26217.  
  26218.  /********************************************************************/
  26219.  /*                                                                  */
  26220.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  26221.  /*                                                                  */
  26222.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  26223.  /* including the implied warranties of merchantability and fitness, */
  26224.  /* are expressly denied.                                            */
  26225.  /*                                                                  */
  26226.  /* Provided this copyright notice is included, this software may    */
  26227.  /* be freely distributed and not offered for sale.                  */
  26228.  /*                                                                  */
  26229.  /* Changes or modifications may be made and used only by the maker  */
  26230.  /* of same, and not further distributed.  Such modifications should */
  26231.  /* be mailed to the author for consideration for addition to the    */
  26232.  /* software and incorporation in subsequent releases.               */
  26233.  /*                                                                  */
  26234.  /********************************************************************/
  26235.  
  26236. /* ----------------- "nnptree.h" include member -------------------- */
  26237.  
  26238. #define ALLOC(X,Y)   GETMAIN(X,struct Y,1,#Y);\
  26239.                      if (!(X)) longjmp(bp->jump,ERROR_GETMAIN_FAILURE)
  26240. #define ERR(X)       (NNMbsynt(np,bp,bp->curtok.string,0,X),\
  26241.                       longjmp(bp->jump,ERROR_BAD_EXPRESSION))
  26242. #define LOSE         longjmp(bp->jump,ERROR_SCAN_ERROR)
  26243.  
  26244. #define ERROR_NONE              0
  26245. #define ERROR_TYPE_MISMATCH     1
  26246. #define ERROR_ZERODIVIDE        2
  26247. #define ERROR_GETMAIN_FAILURE   3
  26248. #define ERROR_BAD_EXPRESSION    4
  26249. #define ERROR_SCAN_ERROR        5
  26250.  
  26251. /*-------------------------------------------------------------------*
  26252.  * ptree: defines structure of expressions used by various commands,
  26253.  * including SET, PUT and NNTP.  When these commands are parsed,
  26254.  * a ptree structure is built to be interpreted when the command is
  26255.  * executed.  The structure represents one of the following:
  26256.  *
  26257.  * - a string expression (concatenated strings or string vars)
  26258.  * - a numeric expression (number, number var or arithmetic expr)
  26259.  * - a flag expression (flag, flag var or logical expr)
  26260.  *
  26261.  *-------------------------------------------------------------------*/
  26262.  
  26263. /*-------------------------------------------------------------------*
  26264.  * treetype: type of an expression tree.
  26265.  *-------------------------------------------------------------------*/
  26266.  
  26267. enum treetype   {
  26268.                  NO_TREETYPE,
  26269.                  STRING_TREETYPE,
  26270.                  NUMBER_TREETYPE,
  26271.                  FLAG_TREETYPE
  26272.                 };
  26273.  
  26274. /*-------------------------------------------------------------------*
  26275.  * rhstype:  type of an expression subtree, based on the RHS of a
  26276.  *           production.  Defines the structure of the components
  26277.  *           that make up this subtree.  Note that the types are
  26278.  *           meaningful only within a given production (LHS) type.
  26279.  *-------------------------------------------------------------------*/
  26280.  
  26281. enum rhstype    {
  26282.                  NO_RHSTYPE,
  26283.                  RHSTYPE_A,
  26284.                  RHSTYPE_B,
  26285.                  RHSTYPE_C,
  26286.                  RHSTYPE_D,
  26287.                  RHSTYPE_E
  26288.                 };
  26289.  
  26290. /*-------------------------------------------------------------------*
  26291.  * optype:  type of an operator
  26292.  *-------------------------------------------------------------------*/
  26293.  
  26294. enum optype     {
  26295.                  NO_OP,
  26296.                  AND_OP,
  26297.                  OR_OP,
  26298.                  NOT_OP,
  26299.                  IN_OP,
  26300.                  EQ_OP,
  26301.                  NE_OP,
  26302.                  GT_OP,
  26303.                  LT_OP,
  26304.                  GE_OP,
  26305.                  LE_OP,
  26306.                  ADD_OP,
  26307.                  SUB_OP,
  26308.                  MUL_OP,
  26309.                  DIV_OP
  26310.                 };
  26311.  
  26312. /*-------------------------------------------------------------------*
  26313.  * These types correspond to production LHS's.
  26314.  *-------------------------------------------------------------------*/
  26315.  
  26316. typedef struct exp        *       Exp;
  26317. typedef struct choice     *       Choice;
  26318. typedef struct relation   *       Relation;
  26319. typedef struct value      *       Value;
  26320. typedef struct quantity   *       Quantity;
  26321. typedef struct term       *       Term;
  26322. typedef struct factor     *       Factor;
  26323. typedef struct unop       *       Unop;
  26324. typedef struct addop      *       Addop;
  26325. typedef struct mulop      *       Mulop;
  26326. typedef struct logop      *       Logop;
  26327. typedef struct relop      *       Relop;
  26328. typedef struct constant   *       Constant;
  26329. typedef struct variable   *       Variable;
  26330. typedef struct number     *       Number;
  26331. typedef struct string     *       String;
  26332. typedef struct flag       *       Flag;
  26333.  
  26334. /*-------------------------------------------------------------------*
  26335.  * The following define the top-down LR(1) grammar.
  26336.  *-------------------------------------------------------------------*/
  26337.  
  26338. struct exp      {
  26339.                  enum rhstype           r;
  26340.                  enum symtype           s;
  26341.                  union {
  26342.                         struct {
  26343.                                 Choice          choice1;
  26344.                                }        a;
  26345.                         struct {
  26346.                                 /* "IF" */
  26347.                                 Exp             exp1;
  26348.                                 /* "THEN" */
  26349.                                 Exp             exp2;
  26350.                                 /* "ELSE" */
  26351.                                 Exp             exp3;
  26352.                                }        b;
  26353.                        }                u;
  26354.                 };
  26355.  
  26356. struct choice   {
  26357.                  enum rhstype           r;
  26358.                  enum symtype           s;
  26359.                  union {
  26360.                         struct {
  26361.                                 Relation        relation1;
  26362.                                }        a;
  26363.                         struct {
  26364.                                 Choice          choice1;
  26365.                                 Logop           logop2;
  26366.                                 Relation        relation3;
  26367.                                }        b;
  26368.                        }                u;
  26369.                 };
  26370.  
  26371. struct relation {
  26372.                  enum rhstype           r;
  26373.                  enum symtype           s;
  26374.                  union {
  26375.                         struct {
  26376.                                 Value           value1;
  26377.                                }        a;
  26378.                         struct {
  26379.                                 Value           value1;
  26380.                                 Relop           relop2;
  26381.                                 Value           value3;
  26382.                                }        b;
  26383.                        }                u;
  26384.                 };
  26385.  
  26386. struct value    {
  26387.                  enum rhstype           r;
  26388.                  enum symtype           s;
  26389.                  union {
  26390.                         struct {
  26391.                                 Quantity        quantity1;
  26392.                                }        a;
  26393.                         struct {
  26394.                                 Value           value1;
  26395.                                 Quantity        quantity2;
  26396.                                }        b;
  26397.                        }                u;
  26398.                 };
  26399.  
  26400. struct quantity {
  26401.                  enum rhstype           r;
  26402.                  enum symtype           s;
  26403.                  union {
  26404.                         struct {
  26405.                                 Term            term1;
  26406.                                }        a;
  26407.                         struct {
  26408.                                 Quantity        quantity1;
  26409.                                 Addop           addop2;
  26410.                                 Term            term3;
  26411.                                }        b;
  26412.                        }                u;
  26413.                 };
  26414.  
  26415. struct term     {
  26416.                  enum rhstype           r;
  26417.                  enum symtype           s;
  26418.                  union {
  26419.                         struct {
  26420.                                 Factor          factor1;
  26421.                                }        a;
  26422.                         struct {
  26423.                                 Term            term1;
  26424.                                 Mulop           mulop2;
  26425.                                 Factor          factor3;
  26426.                                }        b;
  26427.                        }                u;
  26428.                 };
  26429.  
  26430. struct factor   {
  26431.                  enum rhstype           r;
  26432.                  enum symtype           s;
  26433.                  union {
  26434.                         struct {
  26435.                                 Constant        constant1;
  26436.                                }        a;
  26437.                         struct {
  26438.                                 Variable        variable1;
  26439.                                }        b;
  26440.                         struct {
  26441.                                 Unop            unop1;
  26442.                                 Factor          factor2;
  26443.                                }        c;
  26444.                         struct {
  26445.                                 /* "(" */
  26446.                                 Exp             exp1;
  26447.                                 /* ")" */
  26448.                                }        d;
  26449.                        }                u;
  26450.                 };
  26451.  
  26452. struct constant {
  26453.                  enum rhstype           r;
  26454.                  enum symtype           s;
  26455.                  union {
  26456.                         struct {
  26457.                                 Number          number1;
  26458.                                }        a;
  26459.                         struct {
  26460.                                 String          string1;
  26461.                                }        b;
  26462.                         struct {
  26463.                                 Flag            flag1;
  26464.                                }        c;
  26465.                        }                u;
  26466.                 };
  26467.  
  26468. struct unop     {
  26469.                  enum optype            op1;    /* + - ! ^ */
  26470.                 };
  26471.  
  26472. struct addop    {
  26473.                  enum optype            op1;    /* + - */
  26474.                 };
  26475.  
  26476. struct mulop    {
  26477.                  enum optype            op1;    /* * / */
  26478.                 };
  26479.  
  26480. struct logop    {
  26481.                  enum optype            op1;    /* AND OR */
  26482.                 };
  26483.  
  26484. struct relop    {
  26485.                  enum optype            op1;    /* EQ GT LE NE IN... */
  26486.                 };
  26487.  
  26488. struct variable {
  26489.                  enum symtype           s;
  26490.                  char *                 variable1;
  26491.                 };
  26492.  
  26493. struct number   {
  26494.                  enum symtype           s;
  26495.                  int                    number1;
  26496.                 };
  26497.  
  26498. struct string   {
  26499.                  enum symtype           s;
  26500.                  char                  *string1;
  26501.                 };
  26502.  
  26503. struct flag     {
  26504.                  enum symtype           s;
  26505.                  Fool                   flag1;  /* ON OFF TRUE FALSE */
  26506.                 };
  26507.  
  26508. /*-------------------------------------------------------------------*
  26509.  * thing: describes entity to be returned from a ptree at run time
  26510.  *-------------------------------------------------------------------*/
  26511.  
  26512. struct thing    {
  26513.                  ANYTYPE                val;    /* char *, int, Fool */
  26514.                  enum symtype           typ;    /* string/number/flag*/
  26515.                 };
  26516.  
  26517. /*-------------------------------------------------------------------*
  26518.  * ptree: expression tree.  Root of string/number/flag expression
  26519.  *-------------------------------------------------------------------*/
  26520.  
  26521. struct ptree    {
  26522.                  enum symtype           type;   /* string/number/flag*/
  26523.                  Exp                    exp1;   /* actual expression */
  26524.                 };
  26525.  
  26526. ./   ADD NAME=NNSASC,SSI=01000006
  26527.  
  26528.  /********************************************************************/
  26529.  /*                                                                  */
  26530.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  26531.  /*                                                                  */
  26532.  /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.          */
  26533.  /*                                                                  */
  26534.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  26535.  /* including the implied warranties of merchantability and fitness, */
  26536.  /* are expressly denied.                                            */
  26537.  /*                                                                  */
  26538.  /* Provided this copyright notice is included, this software may    */
  26539.  /* be freely distributed and not offered for sale.                  */
  26540.  /*                                                                  */
  26541.  /* Changes or modifications may be made and used only by the maker  */
  26542.  /* of same, and not further distributed.  Such modifications should */
  26543.  /* be mailed to the author for consideration for addition to the    */
  26544.  /* software and incorporation in subsequent releases.               */
  26545.  /*                                                                  */
  26546.  /********************************************************************/
  26547.  
  26548. /* ------------------- "nnsasc.h" include member ------------------- */
  26549.  
  26550. #ifdef SASC
  26551.  
  26552. #define I370
  26553.  
  26554. #include <dynam.h>
  26555.  
  26556. #define FETCH
  26557.  
  26558.  __inline void (*fetch( const char *modname ))()
  26559.  {
  26560.    void (**fpp)();
  26561.  
  26562.    loadm( modname, &fpp );
  26563.    return( *fpp );
  26564.  }
  26565.  
  26566.  __inline int (*release( void (*fpp)() ))
  26567.  {
  26568.    unloadm( fpp );
  26569.    return( 0 );
  26570.  }
  26571.  
  26572.  
  26573. #ifndef __SVC99
  26574.  
  26575.   #define __SVC99  1
  26576.  
  26577.   #include <code.h>
  26578.  
  26579.   struct __S99struc
  26580.     {
  26581.       unsigned char   __S99RBLN;  /* length of request block..20      */
  26582.       unsigned char   __S99VERB;  /* verb code                        */
  26583.       unsigned short  __S99FLAG1; /* FLAGS1 field of SVC99 Req Block  */
  26584.       unsigned short  __S99ERROR; /* error code field                 */
  26585.       unsigned short  __S99INFO;  /* information reason code          */
  26586.       void           *__S99TXTPP; /* address of text unit pointer list*/
  26587.       int             __reserved; /* reserved..will always be 0       */
  26588.       unsigned int    __S99FLAG2; /* FLAGS2 field..can only be filled */
  26589.                                   /* in by APF authorized programs    */
  26590.     };
  26591.  
  26592.   typedef struct __S99struc __S99parms;
  26593.  
  26594.   __inline int svc99(__S99parms* svc99parmlist)
  26595.     { return( (_ldregs(R1, &svc99parmlist),
  26596.                _code(0, 0x0a63),
  26597.                _stregs(R15) ) );
  26598.     }
  26599.  
  26600. #endif
  26601.  
  26602. #define FALSE 0
  26603. #define TRUE  1
  26604.  
  26605. #include <lcio.h>
  26606.  
  26607. #define  MAXHOSTNAMELEN     64
  26608.  
  26609. #define  __ctest(X)  fprintf(stderr,\
  26610.                      "NNMVS: CTEST is not supported by this compiler.")
  26611.  
  26612. #endif
  26613.  
  26614. ./   ADD NAME=NNUSER,SSI=01050047
  26615.  
  26616.  /********************************************************************/
  26617.  /*                                                                  */
  26618.  /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992    */
  26619.  /*                                                                  */
  26620.  /* This software is provided on an "AS IS" basis.  All warranties,  */
  26621.  /* including the implied warranties of merchantability and fitness, */
  26622.  /* are expressly denied.                                            */
  26623.  /*                                                                  */
  26624.  /* Provided this copyright notice is included, this software may    */
  26625.  /* be freely distributed and not offered for sale.                  */
  26626.  /*                                                                  */
  26627.  /* Changes or modifications may be made and used only by the maker  */
  26628.  /* of same, and not further distributed.  Such modifications should */
  26629.  /* be mailed to the author for consideration for addition to the    */
  26630.  /* software and incorporation in subsequent releases.               */
  26631.  /*                                                                  */
  26632.  /********************************************************************/
  26633.  
  26634. /* ------------------- "nnuser.h" include member ------------------- */
  26635.  
  26636. /* Include file for locally customized values. */
  26637.  
  26638. /* Define levels of C/370 and TCP/IP.  This controls support for
  26639.  * fetching of non-C load modules and socket error reporting.
  26640.  */
  26641.  
  26642. /* #define  C370V1    /* define this if C/370 Version 1 */
  26643.    #define  C370V2    /* define this if C/370 Version 2 or higher */
  26644. /* #define  SASC      /* define this if SAS/C compiler */
  26645.  
  26646. /* #define  TCPIPV1   /* define this if TCP/IP Version 1 */
  26647.    #define  TCPIPV2   /* define this if TCP/IP Version 2 or higher */
  26648. /* #define  SNSTCPIP  /* define this if SNS/TCPAccess    */
  26649.  
  26650. /* #define  ISPFV2    /* define this if ISPF Version 2 or earlier */
  26651.    #define  ISPFV3    /* define this if ISPF Version 3 or later
  26652.  
  26653. /* Define the following defaults for your installation. */
  26654.  
  26655. /*
  26656.  * Specify the "user name" portion of the "Sender:" address generated
  26657.  * by posting and mailing requests.
  26658.  *
  26659.  */
  26660.  
  26661. #define NNMVS_NAME  "NNMVS"
  26662.  
  26663. /*
  26664.  * Specify the name of the authorization file used to pass AUTHINFO
  26665.  * requests to the server, if the server requires.  This file should
  26666.  * be readable only by NNMVS if possible.  See the sample authorization
  26667.  * file (AUTH) for the format.
  26668.  *
  26669.  */
  26670.  
  26671. /* #define AUTHFILE    "SYS4.NNTP.SYS"  */
  26672.    #undef  AUTHFILE
  26673.  
  26674. /*
  26675.  * Turn on for TCP-level debugging output (you probably don't want to
  26676.  * unless your TCP/IP stuff is really broken and I can't help you).
  26677.  */
  26678.  
  26679. /* #define DEBUG       */
  26680.    #undef  DEBUG
  26681.  
  26682. /*
  26683.  * Define this if you want DEST, FORMS and UCS for print requests.
  26684.  * Undefine it if you don't (you get just CLASS and COPIES).
  26685.  */
  26686.  
  26687. /* #define FULLSYSOUT  */
  26688.    #undef  FULLSYSOUT
  26689.  
  26690. ./ ENDUP 
  26691. ?!
  26692. //PANELS   EXEC NNLOAD,TRK1='10',TO='PANELS'
  26693. //SYSIN    DD DATA,DLM='?!'
  26694. ./   ADD NAME=COPYRITE,SSI=01000028
  26695. /*                                                                   /*
  26696. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  26697. /*                                                                   /*
  26698. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  26699. /*                                                                   /*
  26700. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  26701. /* including the implied warranties of merchantability and fitness,  /*
  26702. /* are expressly denied.                                             /*
  26703. /*                                                                   /*
  26704. /* Provided this copyright notice is included, this software may     /*
  26705. /* be freely distributed and not offered for sale.                   /*
  26706. /*                                                                   /*
  26707. /* Changes or modifications may be made and used only by the maker   /*
  26708. /* of same, and not further distributed.  Such modifications should  /*
  26709. /* be mailed to the author for consideration for addition to the     /*
  26710. /* software and incorporation in subsequent releases.                /*
  26711. /*                                                                   /*
  26712. ./   ADD NAME=NNL,SSI=01010002
  26713. )ATTR
  26714.  ~ TYPE(INPUT)  INTENS(HIGH) PAD('_')
  26715.  # TYPE(INPUT)  INTENS(LOW)  CAPS(OFF)
  26716.  $ TYPE(INPUT)  INTENS(LOW)  CAPS(ON)
  26717. )BODY
  26718. %---------------  NETNEWS SERVER SELECTION MENU  -------------------------------
  26719. %Command ===>_ZCMD                                            %Scroll ===>_AMT +
  26720. %
  26721. +Line commands:    %D+(Delete) %I+(Insert) %R+(Replicate) %S+(Select)
  26722. %
  26723. %    Server                                       NEWSRC dsname
  26724. %    -------------------------------------------- ------------------------------
  26725. )MODEL
  26726. %~Z%#SERVER                                      $NEWSRC
  26727. )INIT
  26728.   .ZVARS = '(NNSEL)'
  26729.   &AMT = &ZSCML
  26730. )PROC
  26731.   IF (&ZCMD ^= &Z) .MSG = ISPZ001
  26732.   &ZSCML = &AMT
  26733.   VPUT (ZSCML) PROFILE
  26734. )END
  26735.  /* Panel due to Leonard D. Woren <ldw@mvsa.usc.edu>. */
  26736. ./   ADD NAME=NNM,SSI=01210007
  26737. )ATTR
  26738. /*                                                                   /*
  26739. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  26740. /*                                                                   /*
  26741. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  26742. /*                                                                   /*
  26743. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  26744. /* including the implied warranties of merchantability and fitness,  /*
  26745. /* are expressly denied.                                             /*
  26746. /*                                                                   /*
  26747. /* Provided this copyright notice is included, this software may     /*
  26748. /* be freely distributed and not offered for sale.                   /*
  26749. /*                                                                   /*
  26750. /* Changes or modifications may be made and used only by the maker   /*
  26751. /* of same, and not further distributed.  Such modifications should  /*
  26752. /* be mailed to the author for consideration for addition to the     /*
  26753. /* software and incorporation in subsequent releases.                /*
  26754. /*                                                                   /*
  26755.  ^ TYPE(INPUT) INTENS(HIGH) COLOR(GREEN) CAPS(OFF)
  26756.  ! TYPE(TEXT)  INTENS(HIGH) COLOR(RED)
  26757. )BODY EXPAND(``)
  26758. %-`-`-  MVS Network News Viewer -`-`-
  26759. %COMMAND ===>_ZCMD
  26760. +
  26761. +Select one of the following options:
  26762. +
  26763. + %L+or%blank+   - List all newsgroups from server
  26764. + %N +NEWGROUPS  - List new newsgroups from server since last N or L
  26765. + %A +ALL        - Select items from all newsgroups listed in NEWSRC file
  26766. + %R +REGISTERED - Select items from registered newsgroups in NEWSRC file
  26767. + %G +GROUP      - Go directly to the newsgroup named below
  26768. + %NNTP+         - Enter native NNTP protocol commands
  26769. + %OPTions+      - Specify NNMVS defaults
  26770. + %X +EXIT       - Bye
  26771. +
  26772. %Newsgroup name +(if option G selected)%===>^NNGROUPI
  26773. +
  26774. %News server host name+(or IP address) %===>_NNSERVER
  26775. +
  26776. %Name of NEWSRC data set               %===>_NNNEWSRF
  26777. +
  26778. +Press!END+key to leave this menu.
  26779. )INIT
  26780.  .HELP = TNNM
  26781.  IF (&NNCURSOR = &Z)
  26782.   IF (&NNSERVER = &Z)
  26783.    .CURSOR = NNSERVER
  26784.   ELSE
  26785.    .CURSOR = ZCMD
  26786.  ELSE
  26787.   .CURSOR = &NNCURSOR
  26788.  &ZCMD = &Z
  26789.  IF (&NNREGNNG = &Z) &NNREGNNG = PROMPT
  26790.  IF (&NNNEWSRF = &Z) &NNNEWSRF = NEWSRC
  26791. )PROC
  26792.  IF   (&NNGROUPI ^= &Z) VER(&ZCMD,NB)
  26793.  IF   (&ZCMD = ' ')  &ZCMD = 'L'      /* remove if you hate BLANK */
  26794.  &ZCMD = TRANS(&ZCMD A,A R,R L,L G,G N,N
  26795.                      O,O OPT,O OPTIONS,O NNTP,P P,P X,X LD,Z *,?)
  26796.  IF   (&ZCMD ^= 'X') VER (&NNSERVER,NB)
  26797.  IF   (&ZCMD = 'G')  VER (&NNGROUPI,NB)
  26798.  &NNREGNNG = TRUNC(&NNREGNNG,1)
  26799.  VER  (&NNREGNNG,NB,LIST,Y,N,P)
  26800.  VER  (&NNNEWSRF,NB,DSNAME)
  26801.  &TEMP1 = TRUNC(&NNNEWSRF,1)
  26802.  &TEMP2 = .TRAIL
  26803.  IF (&TEMP1 = '''')
  26804.   &NNNEWSRC = TRUNC(&TEMP2,'''')
  26805.  ELSE
  26806.   &NNNEWSRC = '&ZPREFIX..&NNNEWSRF'
  26807.  VPUT (NNGROUPI NNSERVER NNREGNNG NNNEWSRF) PROFILE
  26808. )END
  26809. ./   ADD NAME=NNMDAR,SSI=010A0020
  26810. )ATTR DEFAULT(%+\)
  26811. /*                                                                   /*
  26812. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  26813. /*                                                                   /*
  26814. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  26815. /* including the implied warranties of merchantability and fitness,  /*
  26816. /* are expressly denied.                                             /*
  26817. /*                                                                   /*
  26818. /* Provided this copyright notice is included, this software may     /*
  26819. /* be freely distributed and not offered for sale.                   /*
  26820. /*                                                                   /*
  26821. /* Changes or modifications may be made and used only by the maker   /*
  26822. /* of same, and not further distributed.  Such modifications should  /*
  26823. /* be mailed to the author for consideration for addition to the     /*
  26824. /* software and incorporation in subsequent releases.                /*
  26825. /*                                                                   /*
  26826.  ~ TYPE(INPUT) INTENS(HIGH)  CAPS(OFF) JUST(LEFT)
  26827.  ^ TYPE(INPUT) INTENS(HIGH)  CAPS(OFF) JUST(LEFT)
  26828.  |  AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
  26829.  01 TYPE(DATAOUT) INTENS(LOW)
  26830.  02 TYPE(DATAOUT) INTENS(HIGH)
  26831.  03 TYPE(DATAIN)  INTENS(LOW)
  26832.  04 TYPE(DATAIN)  INTENS(HIGH)
  26833.  05 TYPE(DATAOUT) COLOR(GREEN)
  26834.  06 TYPE(DATAOUT) COLOR(PINK)
  26835.  07 TYPE(DATAOUT) COLOR(RED)
  26836.  08 TYPE(DATAOUT) COLOR(TURQ)
  26837.  09 TYPE(DATAOUT) COLOR(YELLOW)
  26838.  0A TYPE(DATAIN)  COLOR(BLUE)
  26839.  0B TYPE(DATAIN)  COLOR(PINK)
  26840.  0C TYPE(DATAIN)  COLOR(TURQ)
  26841.  0D TYPE(DATAIN)  COLOR(WHITE)
  26842.  0E TYPE(DATAIN)  COLOR(YELLOW)
  26843. )BODY EXPAND(``)
  26844. %&NNTHEAD
  26845. %COMMAND ===>~NNTCMD                                          %SCROLL ===>^NNTS+
  26846. +                                                                              %
  26847. Article:%S+select%E+extract%P+print%M+mark%U+unmark%C+cancel%Status   Date
  26848.  _______________________________________________________________________________
  26849. |NNTDYNA                                                                       |
  26850. )INIT
  26851.  .HELP = TNNMT
  26852.  IF (&NNTS = &Z) &NNTS = CSR
  26853.  IF (&NNTCSR ^= 0)
  26854.   .CURSOR=NNTDYNA
  26855.   .CSRPOS=&NNTCSR
  26856. )PROC
  26857.  &NNTLVL = LVLINE(NNTDYNA)
  26858.  VPUT (NNTS) PROFILE
  26859. )END
  26860. ./   ADD NAME=NNMDBOGG,SSI=01050050
  26861. )ATTR DEFAULT(%+_)
  26862. /*                                                                   /*
  26863. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  26864. /*                                                                   /*
  26865. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  26866. /* including the implied warranties of merchantability and fitness,  /*
  26867. /* are expressly denied.                                             /*
  26868. /*                                                                   /*
  26869. /* Provided this copyright notice is included, this software may     /*
  26870. /* be freely distributed and not offered for sale.                   /*
  26871. /*                                                                   /*
  26872. /* Changes or modifications may be made and used only by the maker   /*
  26873. /* of same, and not further distributed.  Such modifications should  /*
  26874. /* be mailed to the author for consideration for addition to the     /*
  26875. /* software and incorporation in subsequent releases.                /*
  26876. /*                                                                   /*
  26877.  ^  TYPE(INPUT)  INTENS(HIGH) CAPS(ON) JUST(LEFT)
  26878.  |  AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
  26879.  01 TYPE(DATAOUT) INTENS(LOW)
  26880.  02 TYPE(DATAOUT) INTENS(HIGH)
  26881.  03 TYPE(DATAIN)  INTENS(LOW)
  26882.  04 TYPE(DATAIN)  INTENS(HIGH)
  26883. )BODY EXPAND(``)
  26884. %-`-`- Unknown Newsgroups (found in NEWSRC but not by server) -`-`-
  26885. %COMMAND ===>^ZCMD                                            %SCROLL ===>_AMT +
  26886.  
  26887. +Groups displayed will be deleted from NEWSRC.  Scroll up/down to see all.
  26888. +Type%K+to keep a group,%D+to delete. %&END+to accept. %QUIT+or%CANCEL+to abort.
  26889. -------------------------------------------------------------------------------+
  26890. |NNDYNA                                                                        |
  26891. )INIT
  26892.  .HELP = TNNM
  26893.  &END = PFK(END)
  26894.  IF (&AMT = &Z) &AMT = CSR
  26895.  IF (&NNDB1ST = &Z)
  26896.   &NNDB1ST = NO
  26897.   .ALARM = YES
  26898. )PROC
  26899.  VER (&ZCMD,LIST,QUIT,CAN,CANCEL)
  26900.  &NNLVL = LVLINE(NNDYNA)
  26901. )END
  26902. ./   ADD NAME=NNMDNEWG,SSI=01080002
  26903. )ATTR DEFAULT(%+_)
  26904. /*                                                                   /*
  26905. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  26906. /*                                                                   /*
  26907. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  26908. /* including the implied warranties of merchantability and fitness,  /*
  26909. /* are expressly denied.                                             /*
  26910. /*                                                                   /*
  26911. /* Provided this copyright notice is included, this software may     /*
  26912. /* be freely distributed and not offered for sale.                   /*
  26913. /*                                                                   /*
  26914. /* Changes or modifications may be made and used only by the maker   /*
  26915. /* of same, and not further distributed.  Such modifications should  /*
  26916. /* be mailed to the author for consideration for addition to the     /*
  26917. /* software and incorporation in subsequent releases.                /*
  26918. /*                                                                   /*
  26919.  ^  TYPE(INPUT)  INTENS(HIGH) CAPS(ON) JUST(LEFT)
  26920.  |  AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
  26921.  01 TYPE(DATAOUT) INTENS(LOW)
  26922.  02 TYPE(DATAOUT) INTENS(HIGH)
  26923.  03 TYPE(DATAIN)  INTENS(LOW)
  26924.  04 TYPE(DATAIN)  INTENS(HIGH)
  26925. )BODY EXPAND(``)
  26926. %-`-`- New Newsgroups -`-`-
  26927. %COMMAND ===>^ZCMD                                            %SCROLL ===>_AMT +
  26928.  
  26929. +Type%R+to register a newsgroup; %D+to deregister. Scroll up/down to see all.
  26930. +Registered group names highlighted. %&END+to accept. %QUIT+or%CANCEL+to abort.
  26931. -------------------------------------------------------------------------------+
  26932. |NNDYNA                                                                        |
  26933. )INIT
  26934.  .HELP = TNNM
  26935.  &END = PFK(END)
  26936.  IF (&AMT = &Z) &AMT = CSR
  26937.  IF (&NNDN1ST = &Z)
  26938.   &NNDN1ST = NO
  26939.   .ALARM = YES
  26940. )PROC
  26941.  VER (&ZCMD,LIST,QUIT,CAN,CANCEL)
  26942.  &NNLVL = LVLINE(NNDYNA)
  26943. )END
  26944. ./   ADD NAME=NNMDNG,SSI=01070008
  26945. )ATTR
  26946. /*                                                                   /*
  26947. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  26948. /*                                                                   /*
  26949. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  26950. /* including the implied warranties of merchantability and fitness,  /*
  26951. /* are expressly denied.                                             /*
  26952. /*                                                                   /*
  26953. /* Provided this copyright notice is included, this software may     /*
  26954. /* be freely distributed and not offered for sale.                   /*
  26955. /*                                                                   /*
  26956. /* Changes or modifications may be made and used only by the maker   /*
  26957. /* of same, and not further distributed.  Such modifications should  /*
  26958. /* be mailed to the author for consideration for addition to the     /*
  26959. /* software and incorporation in subsequent releases.                /*
  26960. /*                                                                   /*
  26961.  ~ TYPE(INPUT) INTENS(HIGH)  CAPS(OFF) JUST(LEFT)
  26962.  ^ TYPE(INPUT) INTENS(HIGH)  CAPS(OFF) JUST(LEFT)
  26963.  ! TYPE(OUTPUT) INTENS(LOW)  CAPS(OFF) JUST(RIGHT) COLOR(YELLOW)
  26964.  # TYPE(OUTPUT) INTENS(LOW)  CAPS(OFF) JUST(RIGHT) COLOR(BLUE)
  26965.  @ TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(RIGHT) COLOR(PINK)
  26966.  ? TYPE(OUTPUT) INTENS(LOW)  CAPS(OFF) JUST(LEFT)  COLOR(TURQ) PAD('.')
  26967.  |  AREA(DYNAMIC) EXTEND(ON) SCROLL(ON)
  26968.  \  AREA(DYNAMIC) EXTEND(OFF) SCROLL(OFF)
  26969.  01 TYPE(DATAOUT) INTENS(LOW)
  26970.  02 TYPE(DATAOUT) INTENS(HIGH)
  26971.  03 TYPE(DATAIN)  INTENS(LOW)
  26972.  04 TYPE(DATAIN)  INTENS(HIGH)
  26973.  05 TYPE(DATAOUT) COLOR(GREEN)
  26974.  06 TYPE(DATAOUT) COLOR(PINK)
  26975.  07 TYPE(DATAOUT) COLOR(RED)
  26976.  08 TYPE(DATAOUT) COLOR(TURQ)
  26977.  09 TYPE(DATAOUT) COLOR(YELLOW)
  26978.  0A TYPE(DATAIN)  COLOR(BLUE)
  26979.  0B TYPE(DATAIN)  COLOR(PINK)
  26980.  0C TYPE(DATAIN)  COLOR(TURQ)
  26981.  0D TYPE(DATAIN)  COLOR(WHITE)
  26982.  0E TYPE(DATAIN)  COLOR(YELLOW)
  26983. )BODY EXPAND(``)
  26984. %&NNGHEAD
  26985. %COMMAND ===>~NNGCMD                                          %SCROLL ===>^NNGS+
  26986. +
  26987. \NNGLINE                                                                       \
  26988.  -------------------------------------------------------------------------------
  26989. |NNGDYNA                                                                       |
  26990. )INIT
  26991.  .HELP = TNNMG
  26992.  IF (&NNGS = &Z) &NNGS = CSR
  26993.  IF (&NNGCSR ^= 0)
  26994.   .CURSOR=NNGDYNA
  26995.   .CSRPOS=&NNGCSR
  26996. )PROC
  26997.  &NNGLVL = LVLINE(NNGDYNA)
  26998.  VPUT (NNGS) PROFILE
  26999. )END
  27000. ./   ADD NAME=NNMLADDG,SSI=01020000
  27001. )ATTR
  27002. /*                                                                   /*
  27003. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27004. /*                                                                   /*
  27005. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27006. /* including the implied warranties of merchantability and fitness,  /*
  27007. /* are expressly denied.                                             /*
  27008. /*                                                                   /*
  27009. /* Provided this copyright notice is included, this software may     /*
  27010. /* be freely distributed and not offered for sale.                   /*
  27011. /*                                                                   /*
  27012. /* Changes or modifications may be made and used only by the maker   /*
  27013. /* of same, and not further distributed.  Such modifications should  /*
  27014. /* be mailed to the author for consideration for addition to the     /*
  27015. /* software and incorporation in subsequent releases.                /*
  27016. /*                                                                   /*
  27017.  @ TYPE(OUTPUT) INTENS(LOW)
  27018. )BODY EXPAND(``)
  27019. %-`-`-  MVS Network News Connection -`-`-
  27020. +
  27021. +
  27022.          Adding newsgroup:
  27023. %        &NNLGROUP
  27024. +
  27025.          (Estimated number of articles...&NNLCOUNT)
  27026. +        @NNDUMMY
  27027. +
  27028.                                  % Please wait.
  27029. +
  27030. +
  27031. )INIT
  27032. )PROC
  27033. )END
  27034. ./   ADD NAME=NNMLADD2,SSI=01010017
  27035. )ATTR DEFAULT(|+_)
  27036. /*                                                                   /*
  27037. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27038. /*                                                                   /*
  27039. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27040. /*                                                                   /*
  27041. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27042. /* including the implied warranties of merchantability and fitness,  /*
  27043. /* are expressly denied.                                             /*
  27044. /*                                                                   /*
  27045. /* Provided this copyright notice is included, this software may     /*
  27046. /* be freely distributed and not offered for sale.                   /*
  27047. /*                                                                   /*
  27048. /* Changes or modifications may be made and used only by the maker   /*
  27049. /* of same, and not further distributed.  Such modifications should  /*
  27050. /* be mailed to the author for consideration for addition to the     /*
  27051. /* software and incorporation in subsequent releases.                /*
  27052. /*                                                                   /*
  27053.  ^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
  27054.  / TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
  27055.  * AREA(DYNAMIC)
  27056. )BODY EXPAND(``)
  27057. |-`-`-  MVS Network News Connection -`-`-
  27058. +
  27059.  
  27060.          Now adding newsgroups
  27061.  
  27062. +
  27063.          Percentage of news groups processed:
  27064.          ------------------------------------------------------------
  27065.         *NNMBAR                                                     *|&NNMCOUNT
  27066. +        ------------------------------------------------------------
  27067.         0%                          50%                              100%
  27068.  
  27069.      This may take a long time, depending on the number of newsgroups.
  27070.  
  27071.  
  27072. |                                  Please wait.
  27073.  
  27074. )INIT
  27075. )PROC
  27076. )END
  27077. ./   ADD NAME=NNMLADD3,SSI=01000012
  27078. )ATTR DEFAULT(|+_)
  27079. /*                                                                   /*
  27080. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27081. /*                                                                   /*
  27082. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27083. /*                                                                   /*
  27084. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27085. /* including the implied warranties of merchantability and fitness,  /*
  27086. /* are expressly denied.                                             /*
  27087. /*                                                                   /*
  27088. /* Provided this copyright notice is included, this software may     /*
  27089. /* be freely distributed and not offered for sale.                   /*
  27090. /*                                                                   /*
  27091. /* Changes or modifications may be made and used only by the maker   /*
  27092. /* of same, and not further distributed.  Such modifications should  /*
  27093. /* be mailed to the author for consideration for addition to the     /*
  27094. /* software and incorporation in subsequent releases.                /*
  27095. /*                                                                   /*
  27096.  ^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
  27097.  / TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
  27098.  * AREA(DYNAMIC)
  27099. )BODY EXPAND(``)
  27100. |-`-`-  MVS Network News Connection -`-`-
  27101. +
  27102.  
  27103.          Now adding newsgroup:
  27104.         |&NNLGROUP
  27105. +
  27106.          Percentage of news groups processed:
  27107.          ------------------------------------------------------------
  27108.         *NNMBAR                                                     *|&NNMCOUNT
  27109. +        ------------------------------------------------------------
  27110.         0%                          50%                              100%
  27111.  
  27112.      This may take a long time, depending on the number of newsgroups.
  27113.  
  27114.  
  27115. |                                  Please wait.
  27116.  
  27117. )INIT
  27118. )PROC
  27119. )END
  27120. ./   ADD NAME=NNMLARTS,SSI=01030000
  27121. )ATTR
  27122. /*                                                                   /*
  27123. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27124. /*                                                                   /*
  27125. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27126. /* including the implied warranties of merchantability and fitness,  /*
  27127. /* are expressly denied.                                             /*
  27128. /*                                                                   /*
  27129. /* Provided this copyright notice is included, this software may     /*
  27130. /* be freely distributed and not offered for sale.                   /*
  27131. /*                                                                   /*
  27132. /* Changes or modifications may be made and used only by the maker   /*
  27133. /* of same, and not further distributed.  Such modifications should  /*
  27134. /* be mailed to the author for consideration for addition to the     /*
  27135. /* software and incorporation in subsequent releases.                /*
  27136. /*                                                                   /*
  27137.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27138.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27139.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27140.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27141.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27142.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27143.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27144. )BODY EXPAND(``)
  27145. %-`-`-  MVS Network News Connection -`-`-
  27146. +
  27147. +
  27148.          Now retrieving the titles of the articles in newsgroup:
  27149. %        &NNGROUP
  27150. +
  27151.      This may take a long time, depending on the number of articles.
  27152. +
  27153. +
  27154.                                  % Please wait.
  27155. +
  27156. +
  27157. )INIT
  27158. )PROC
  27159. )END
  27160. ./   ADD NAME=NNMLART2,SSI=01020035
  27161. )ATTR DEFAULT(|+_)
  27162. /*                                                                   /*
  27163. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27164. /*                                                                   /*
  27165. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27166. /*                                                                   /*
  27167. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27168. /* including the implied warranties of merchantability and fitness,  /*
  27169. /* are expressly denied.                                             /*
  27170. /*                                                                   /*
  27171. /* Provided this copyright notice is included, this software may     /*
  27172. /* be freely distributed and not offered for sale.                   /*
  27173. /*                                                                   /*
  27174. /* Changes or modifications may be made and used only by the maker   /*
  27175. /* of same, and not further distributed.  Such modifications should  /*
  27176. /* be mailed to the author for consideration for addition to the     /*
  27177. /* software and incorporation in subsequent releases.                /*
  27178. /*                                                                   /*
  27179.  ^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
  27180.  / TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
  27181.  * AREA(DYNAMIC)
  27182.  $ TYPE(TEXT) INTENS(LOW)
  27183.  # TYPE(OUTPUT) INTENS(HIGH)
  27184. )BODY EXPAND(``)
  27185. |-`-`-  MVS Network News Connection -`-`-
  27186. +
  27187.  
  27188.          Now retrieving the titles of the articles in newsgroup:
  27189.         |&NNGROUP
  27190. +
  27191.          &MSG
  27192. +        ------------------------------------------------------------
  27193.         *NNMBAR                                                     *|&TODO
  27194. +        ------------------------------------------------------------
  27195.         0%                          50%                              100%
  27196.  
  27197.         $Estimated time to completion:#NNMESTM +
  27198.  
  27199.      This may take a long time, depending on the number of articles.
  27200.  
  27201.  
  27202. |                                  Please wait.
  27203.  
  27204. )INIT
  27205.  IF (&NNMESTM = &Z)
  27206.    .ATTRCHAR($) = 'INTENS(NON)'
  27207.    .ATTRCHAR(#) = 'INTENS(NON)'
  27208.  IF (&NNMCOUNT = -1)
  27209.   &TODO = &Z
  27210.   &MSG = 'Articles processed so far while searching:'
  27211.  ELSE
  27212.   &TODO = &NNMCOUNT
  27213.   &MSG = 'Percentage of articles processed so far:'
  27214. )PROC
  27215. )END
  27216. ./   ADD NAME=NNMLCONN,SSI=01030000
  27217. )ATTR
  27218. /*                                                                   /*
  27219. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27220. /*                                                                   /*
  27221. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27222. /* including the implied warranties of merchantability and fitness,  /*
  27223. /* are expressly denied.                                             /*
  27224. /*                                                                   /*
  27225. /* Provided this copyright notice is included, this software may     /*
  27226. /* be freely distributed and not offered for sale.                   /*
  27227. /*                                                                   /*
  27228. /* Changes or modifications may be made and used only by the maker   /*
  27229. /* of same, and not further distributed.  Such modifications should  /*
  27230. /* be mailed to the author for consideration for addition to the     /*
  27231. /* software and incorporation in subsequent releases.                /*
  27232. /*                                                                   /*
  27233.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27234.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27235.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27236.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27237.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27238.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27239.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27240. )BODY EXPAND(``)
  27241. %-`-`-  MVS Network News Connection -`-`-
  27242. +
  27243. +             Client name: &NNCLIENT    Client IP address:  &NNCLIEIP
  27244. +
  27245. +
  27246. +             Connection is in progress for news server at:
  27247.               &NNSERVER (&NNSERVIP)
  27248. +
  27249. +
  27250.                                  % Please wait.
  27251. +
  27252. +
  27253. )INIT
  27254. )PROC
  27255. )END
  27256. ./   ADD NAME=NNMLDISC,SSI=01050000
  27257. )ATTR
  27258. /*                                                                   /*
  27259. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27260. /*                                                                   /*
  27261. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27262. /* including the implied warranties of merchantability and fitness,  /*
  27263. /* are expressly denied.                                             /*
  27264. /*                                                                   /*
  27265. /* Provided this copyright notice is included, this software may     /*
  27266. /* be freely distributed and not offered for sale.                   /*
  27267. /*                                                                   /*
  27268. /* Changes or modifications may be made and used only by the maker   /*
  27269. /* of same, and not further distributed.  Such modifications should  /*
  27270. /* be mailed to the author for consideration for addition to the     /*
  27271. /* software and incorporation in subsequent releases.                /*
  27272. /*                                                                   /*
  27273.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27274.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27275.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27276.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27277.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27278.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27279.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27280. )BODY EXPAND(``)
  27281. %-`-`-  MVS Network News Connection -`-`-
  27282. +
  27283. +
  27284. +         Disconnection is in progress from the news server at:
  27285.           &NNSOLDER (&NNSOLDIP)
  27286. +
  27287. +
  27288.                                  % Please wait.
  27289. +
  27290. +
  27291. )INIT
  27292. )PROC
  27293. )END
  27294. ./   ADD NAME=NNMLEXN2,SSI=01010000
  27295. )ATTR
  27296. /*                                                                   /*
  27297. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27298. /*                                                                   /*
  27299. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27300. /* including the implied warranties of merchantability and fitness,  /*
  27301. /* are expressly denied.                                             /*
  27302. /*                                                                   /*
  27303. /* Provided this copyright notice is included, this software may     /*
  27304. /* be freely distributed and not offered for sale.                   /*
  27305. /*                                                                   /*
  27306. /* Changes or modifications may be made and used only by the maker   /*
  27307. /* of same, and not further distributed.  Such modifications should  /*
  27308. /* be mailed to the author for consideration for addition to the     /*
  27309. /* software and incorporation in subsequent releases.                /*
  27310. /*                                                                   /*
  27311.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27312.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27313.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27314.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27315.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27316.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27317. )BODY EXPAND(``)
  27318. %-`-`-  MVS Network News Connection -`-`-
  27319. +
  27320. +Newsgroup: &NNLGROUP
  27321. +
  27322. +Article #:%&NNTNUM
  27323. +Subject:   &NNTSUBJ
  27324. +
  27325. +Extracting to: &NNEXDSN
  27326. +&MEMSTUFF
  27327. +
  27328.                                  % Please wait.
  27329. +
  27330. )INIT
  27331.  IF (&NNEXMEM = &Z) &MEMSTUFF = &Z
  27332.  ELSE               &MEMSTUFF = 'Member: &NNEXMEM'
  27333. )PROC
  27334. )END
  27335. ./   ADD NAME=NNMLLIST,SSI=01030000
  27336. )ATTR
  27337. /*                                                                   /*
  27338. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27339. /*                                                                   /*
  27340. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27341. /* including the implied warranties of merchantability and fitness,  /*
  27342. /* are expressly denied.                                             /*
  27343. /*                                                                   /*
  27344. /* Provided this copyright notice is included, this software may     /*
  27345. /* be freely distributed and not offered for sale.                   /*
  27346. /*                                                                   /*
  27347. /* Changes or modifications may be made and used only by the maker   /*
  27348. /* of same, and not further distributed.  Such modifications should  /*
  27349. /* be mailed to the author for consideration for addition to the     /*
  27350. /* software and incorporation in subsequent releases.                /*
  27351. /*                                                                   /*
  27352.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27353.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27354.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27355.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27356.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27357.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27358.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27359. )BODY EXPAND(``)
  27360. %-`-`-  MVS Network News Connection -`-`-
  27361. +
  27362. +
  27363.        A list of all newsgroups is being retrieved from the news server at:
  27364.        &NNSERVER (&NNSERVIP)
  27365. +
  27366.      This may take a long time, depending on the number of newsgroups known.
  27367. +
  27368. +
  27369.                                  % Please wait.
  27370. +
  27371. +
  27372. )INIT
  27373. )PROC
  27374. )END
  27375. ./   ADD NAME=NNMLNEWG,SSI=01000032
  27376. )ATTR
  27377. /*                                                                   /*
  27378. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27379. /*                                                                   /*
  27380. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27381. /*                                                                   /*
  27382. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27383. /* including the implied warranties of merchantability and fitness,  /*
  27384. /* are expressly denied.                                             /*
  27385. /*                                                                   /*
  27386. /* Provided this copyright notice is included, this software may     /*
  27387. /* be freely distributed and not offered for sale.                   /*
  27388. /*                                                                   /*
  27389. /* Changes or modifications may be made and used only by the maker   /*
  27390. /* of same, and not further distributed.  Such modifications should  /*
  27391. /* be mailed to the author for consideration for addition to the     /*
  27392. /* software and incorporation in subsequent releases.                /*
  27393. /*                                                                   /*
  27394.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27395.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27396.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27397.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27398.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27399.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27400.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27401. )BODY EXPAND(``)
  27402. %-`-`-  MVS Network News Connection -`-`-
  27403. +
  27404. +
  27405.        A list of new newsgroups since &NNNGDT &NNNGTM is being retrieved
  27406. +      from the news server at:  &NNSERVER (&NNSERVIP)
  27407. +
  27408.      This may take a long time, depending on the number of newsgroups known.
  27409. +
  27410. +
  27411.                                  % Please wait.
  27412. +
  27413. +
  27414. )INIT
  27415. )PROC
  27416. )END
  27417. ./   ADD NAME=NNMLPRN2,SSI=01010059
  27418. )ATTR
  27419. /*                                                                   /*
  27420. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     /*
  27421. /*                                                                   /*
  27422. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27423. /* including the implied warranties of merchantability and fitness,  /*
  27424. /* are expressly denied.                                             /*
  27425. /*                                                                   /*
  27426. /* Provided this copyright notice is included, this software may     /*
  27427. /* be freely distributed and not offered for sale.                   /*
  27428. /*                                                                   /*
  27429. /* Changes or modifications may be made and used only by the maker   /*
  27430. /* of same, and not further distributed.  Such modifications should  /*
  27431. /* be mailed to the author for consideration for addition to the     /*
  27432. /* software and incorporation in subsequent releases.                /*
  27433. /*                                                                   /*
  27434.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27435.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27436.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27437.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27438.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27439.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27440. )BODY EXPAND(``)
  27441. %-`-`-  MVS Network News Connection -`-`-
  27442. +
  27443. +Newsgroup: &NNLGROUP
  27444. +
  27445. +Article #:%&NNTNUM
  27446. +Subject:   &NNTSUBJ
  27447. +
  27448. +Printing to SYSOUT class: &NNEXSCL
  27449. +&MEMSTUFF
  27450. +
  27451.                                  % Please wait.
  27452. +
  27453. )INIT
  27454.  IF (&NNEXMEM = &Z) &MEMSTUFF = &Z
  27455.  ELSE               &MEMSTUFF = 'Member: &NNEXMEM'
  27456. )PROC
  27457. )END
  27458. ./   ADD NAME=NNMLRCON,SSI=01020000
  27459. )ATTR
  27460. /*                                                                   /*
  27461. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27462. /*                                                                   /*
  27463. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27464. /* including the implied warranties of merchantability and fitness,  /*
  27465. /* are expressly denied.                                             /*
  27466. /*                                                                   /*
  27467. /* Provided this copyright notice is included, this software may     /*
  27468. /* be freely distributed and not offered for sale.                   /*
  27469. /*                                                                   /*
  27470. /* Changes or modifications may be made and used only by the maker   /*
  27471. /* of same, and not further distributed.  Such modifications should  /*
  27472. /* be mailed to the author for consideration for addition to the     /*
  27473. /* software and incorporation in subsequent releases.                /*
  27474. /*                                                                   /*
  27475.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27476.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27477.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27478.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27479.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27480.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27481.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27482. )BODY EXPAND(``)
  27483. %-`-`-  MVS Network News Connection -`-`-
  27484. +
  27485.         +Connection has apparently been lost to the news server at:
  27486.         &NNSERVER (&NNSERVIP)
  27487. +
  27488.                 +Reconnection to the server is in progress.
  27489. +
  27490.                                  % Please wait.
  27491. +
  27492. +
  27493. )INIT
  27494. )PROC
  27495. )END
  27496. ./   ADD NAME=NNMLRETG,SSI=01010000
  27497. )ATTR
  27498. /*                                                                   /*
  27499. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27500. /*                                                                   /*
  27501. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27502. /* including the implied warranties of merchantability and fitness,  /*
  27503. /* are expressly denied.                                             /*
  27504. /*                                                                   /*
  27505. /* Provided this copyright notice is included, this software may     /*
  27506. /* be freely distributed and not offered for sale.                   /*
  27507. /*                                                                   /*
  27508. /* Changes or modifications may be made and used only by the maker   /*
  27509. /* of same, and not further distributed.  Such modifications should  /*
  27510. /* be mailed to the author for consideration for addition to the     /*
  27511. /* software and incorporation in subsequent releases.                /*
  27512. /*                                                                   /*
  27513.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27514.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27515.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27516.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27517.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27518.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27519.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27520. )BODY EXPAND(``)
  27521. %-`-`-  MVS Network News Connection -`-`-
  27522. +
  27523. +
  27524.          Retrieving current status of newsgroup:
  27525. %        &NNLGROUP
  27526. +
  27527. +
  27528.                                  % Please wait.
  27529. +
  27530. +
  27531. )INIT
  27532. )PROC
  27533. )END
  27534. ./   ADD NAME=NNMLRET2,SSI=01000019
  27535. )ATTR DEFAULT(|+_)
  27536. /*                                                                   /*
  27537. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27538. /*                                                                   /*
  27539. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27540. /*                                                                   /*
  27541. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27542. /* including the implied warranties of merchantability and fitness,  /*
  27543. /* are expressly denied.                                             /*
  27544. /*                                                                   /*
  27545. /* Provided this copyright notice is included, this software may     /*
  27546. /* be freely distributed and not offered for sale.                   /*
  27547. /*                                                                   /*
  27548. /* Changes or modifications may be made and used only by the maker   /*
  27549. /* of same, and not further distributed.  Such modifications should  /*
  27550. /* be mailed to the author for consideration for addition to the     /*
  27551. /* software and incorporation in subsequent releases.                /*
  27552. /*                                                                   /*
  27553.  ^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
  27554.  / TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
  27555.  * AREA(DYNAMIC)
  27556.  $ TYPE(TEXT) INTENS(LOW)
  27557.  # TYPE(OUTPUT) INTENS(HIGH)
  27558. )BODY EXPAND(``)
  27559. |-`-`-  MVS Network News Connection -`-`-
  27560. +
  27561. +
  27562. +        Retrieving current status of registered newsgroups
  27563. +
  27564. +
  27565. +        Percentage of registered newsgroups processed:
  27566. +        ------------------------------------------------------------
  27567. +       *NNMBAR                                                     *|&NNMCOUNT
  27568. +        ------------------------------------------------------------
  27569. +       0%                          50%                              100%
  27570. +
  27571. +       $Estimated time to completion:#NNMESTM +
  27572. +
  27573. )INIT
  27574.  IF (&NNMESTM = &Z)
  27575.    .ATTRCHAR($) = 'INTENS(NON)'
  27576.    .ATTRCHAR(#) = 'INTENS(NON)'
  27577. )PROC
  27578. )END
  27579. ./   ADD NAME=NNMLRET3,SSI=01000044
  27580. )ATTR DEFAULT(|+_)
  27581. /*                                                                   /*
  27582. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27583. /*                                                                   /*
  27584. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27585. /*                                                                   /*
  27586. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27587. /* including the implied warranties of merchantability and fitness,  /*
  27588. /* are expressly denied.                                             /*
  27589. /*                                                                   /*
  27590. /* Provided this copyright notice is included, this software may     /*
  27591. /* be freely distributed and not offered for sale.                   /*
  27592. /*                                                                   /*
  27593. /* Changes or modifications may be made and used only by the maker   /*
  27594. /* of same, and not further distributed.  Such modifications should  /*
  27595. /* be mailed to the author for consideration for addition to the     /*
  27596. /* software and incorporation in subsequent releases.                /*
  27597. /*                                                                   /*
  27598.  ^ TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ) HILITE(REVERSE)
  27599.  / TYPE(DATAOUT) INTENS(HIGH) COLOR(TURQ)
  27600.  * AREA(DYNAMIC)
  27601.  $ TYPE(TEXT) INTENS(LOW)
  27602.  # TYPE(OUTPUT) INTENS(HIGH)
  27603. )BODY EXPAND(``)
  27604. |-`-`-  MVS Network News Connection -`-`-
  27605. +
  27606. +
  27607. +        Retrieving current status of newsgroup:
  27608. |        &NNLGROUP
  27609. +
  27610. +        Percentage of registered newsgroups processed:
  27611. +        ------------------------------------------------------------
  27612. +       *NNMBAR                                                     *|&NNMCOUNT
  27613. +        ------------------------------------------------------------
  27614. +       0%                          50%                              100%
  27615. +
  27616. +       $Estimated time to completion:#NNMESTM +
  27617. +
  27618. )INIT
  27619.  IF (&NNMESTM = &Z)
  27620.    .ATTRCHAR($) = 'INTENS(NON)'
  27621.    .ATTRCHAR(#) = 'INTENS(NON)'
  27622. )PROC
  27623. )END
  27624. ./   ADD NAME=NNMLRSNG,SSI=01020000
  27625. )ATTR
  27626. /*                                                                   /*
  27627. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27628. /*                                                                   /*
  27629. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27630. /* including the implied warranties of merchantability and fitness,  /*
  27631. /* are expressly denied.                                             /*
  27632. /*                                                                   /*
  27633. /* Provided this copyright notice is included, this software may     /*
  27634. /* be freely distributed and not offered for sale.                   /*
  27635. /*                                                                   /*
  27636. /* Changes or modifications may be made and used only by the maker   /*
  27637. /* of same, and not further distributed.  Such modifications should  /*
  27638. /* be mailed to the author for consideration for addition to the     /*
  27639. /* software and incorporation in subsequent releases.                /*
  27640. /*                                                                   /*
  27641.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27642.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27643.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27644.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27645.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27646.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27647.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27648. )BODY EXPAND(``)
  27649. %-`-`-  MVS Network News Connection -`-`-
  27650. +
  27651. +         Reconnection has been established to the news server at:
  27652.           &NNSERVER (&NNSERVIP)
  27653. +
  27654.           Now reestablishing current newsgroup:
  27655. %         &NNGROUP
  27656. +
  27657.                                  % Please wait.
  27658. +
  27659. +
  27660. )INIT
  27661. )PROC
  27662. )END
  27663. ./   ADD NAME=NNMLUNRC,SSI=01000004
  27664. )ATTR
  27665. /*                                                                   /*
  27666. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27667. /*                                                                   /*
  27668. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27669. /*                                                                   /*
  27670. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27671. /* including the implied warranties of merchantability and fitness,  /*
  27672. /* are expressly denied.                                             /*
  27673. /*                                                                   /*
  27674. /* Provided this copyright notice is included, this software may     /*
  27675. /* be freely distributed and not offered for sale.                   /*
  27676. /*                                                                   /*
  27677. /* Changes or modifications may be made and used only by the maker   /*
  27678. /* of same, and not further distributed.  Such modifications should  /*
  27679. /* be mailed to the author for consideration for addition to the     /*
  27680. /* software and incorporation in subsequent releases.                /*
  27681. /*                                                                   /*
  27682.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  27683.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  27684.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  27685.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  27686.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  27687.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  27688.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  27689. )BODY EXPAND(``)
  27690. %-`-`-  MVS Network News Connection -`-`-
  27691. +
  27692. +
  27693. +                       Updating NEWSRC file &NNNEWSRF ...
  27694. +
  27695. +
  27696. +
  27697. %                                  Please wait.
  27698. +
  27699. +
  27700. )INIT
  27701. )PROC
  27702. )END
  27703. ./   ADD NAME=NNMOPTS,SSI=010B0035
  27704. )ATTR
  27705. /*                                                                   /*
  27706. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27707. /*                                                                   /*
  27708. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27709. /*                                                                   /*
  27710. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27711. /* including the implied warranties of merchantability and fitness,  /*
  27712. /* are expressly denied.                                             /*
  27713. /*                                                                   /*
  27714. /* Provided this copyright notice is included, this software may     /*
  27715. /* be freely distributed and not offered for sale.                   /*
  27716. /*                                                                   /*
  27717. /* Changes or modifications may be made and used only by the maker   /*
  27718. /* of same, and not further distributed.  Such modifications should  /*
  27719. /* be mailed to the author for consideration for addition to the     /*
  27720. /* software and incorporation in subsequent releases.                /*
  27721. /*                                                                   /*
  27722. )BODY EXPAND(``)
  27723. %-`-`- NNMVS - Article Retrieval Options -`-`-
  27724. %Command ===>_ZCMD
  27725. +
  27726. %General options:
  27727.  
  27728. +In-progress screen for adding newsgroups?  (YES/NO)%==>_Z  +
  27729. +In-progress screen for rewriting NEWSRC?   (YES/NO)%==>_Z  +
  27730. +In-progress screen for retrieving articles?(YES/NO)%==>_Z  +
  27731.  
  27732. +Screen update frequency   %==>_Z       + (Enter%ON, OFF,+or%number+of seconds)
  27733.  
  27734. %EXTRACT prompting options:
  27735.  
  27736. +Warning panel before writing over an existing dataset?%==>_Z  +
  27737. +Warning panel before appending to an existing dataset?%==>_Z  +
  27738.  
  27739. +Press%ENTER+to change options.  Press%&END+(or type%END+command) when done.
  27740. )INIT
  27741.  .ZVARS  = '(NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP)'
  27742.  .HELP   = TNNMOPT
  27743.  .CURSOR = ZCMD
  27744.  &END = PFK(END)
  27745.  &ZCMD = &Z
  27746.  VGET (NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP) PROFILE
  27747.  IF (&NNMUPDTF = &Z) &NNMUPDTF = '5'
  27748.  &NNUPAN   = TRANS(TRUNC(&NNUPAN,1)   Y,YES N,NO *,NO )
  27749.  &NNUPRN   = TRANS(TRUNC(&NNUPRN,1)   Y,YES N,NO *,YES)
  27750.  &NNUPRA   = TRANS(TRUNC(&NNUPRA,1)   Y,YES N,NO *,YES)
  27751.  &NNEXTPOW = TRANS(TRUNC(&NNEXTPOW,1) Y,YES N,NO *,YES)
  27752.  &NNEXTPAP = TRANS(TRUNC(&NNEXTPAP,1) Y,YES N,NO *,YES)
  27753. )PROC
  27754.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  27755.  IF (.RESP = ENTER)
  27756.   VER(&NNMUPDTF,NB)
  27757.   IF (&NNMUPDTF = '0')  &NNMUPDTF = 'ON'
  27758.   IF (&NNMUPDTF = 'ON','OFF')
  27759.   ELSE
  27760.     VER(&NNMUPDTF,NUM)
  27761.   &NNUPAN   = TRUNC(&NNUPAN,1)
  27762.   &NNUPRN   = TRUNC(&NNUPRN,1)
  27763.   &NNUPRA   = TRUNC(&NNUPRA,1)
  27764.   &NNEXTPOW = TRUNC(&NNEXTPOW,1)
  27765.   &NNEXTPAP = TRUNC(&NNEXTPAP,1)
  27766.   VER(&NNUPAN  ,NB,LIST,Y,N)
  27767.   VER(&NNUPRN  ,NB,LIST,Y,N)
  27768.   VER(&NNUPRA  ,NB,LIST,Y,N)
  27769.   VER(&NNEXTPOW,NB,LIST,Y,N)
  27770.  VPUT (NNUPAN NNUPRN NNUPRA NNMUPDTF NNEXTPOW NNEXTPAP) PROFILE
  27771. )END
  27772. ./   ADD NAME=NNMOPTT,SSI=01030057
  27773. )ATTR
  27774. /*                                                                   /*
  27775. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27776. /*                                                                   /*
  27777. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  27778. /*                                                                   /*
  27779. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27780. /* including the implied warranties of merchantability and fitness,  /*
  27781. /* are expressly denied.                                             /*
  27782. /*                                                                   /*
  27783. /* Provided this copyright notice is included, this software may     /*
  27784. /* be freely distributed and not offered for sale.                   /*
  27785. /*                                                                   /*
  27786. /* Changes or modifications may be made and used only by the maker   /*
  27787. /* of same, and not further distributed.  Such modifications should  /*
  27788. /* be mailed to the author for consideration for addition to the     /*
  27789. /* software and incorporation in subsequent releases.                /*
  27790. /*                                                                   /*
  27791. )BODY EXPAND(``)
  27792. %-`-`- NNMVS - Table Viewing Options -`-`-
  27793. %Command ===>_ZCMD
  27794. +
  27795. %Newsgroup table options:
  27796.  
  27797. +Scroll last selected newsgroup to top? (YES/NO)%==>_Z  +
  27798. +Put cursor at last selected newsgroup? (YES/NO)%==>_Z  +
  27799.  
  27800. %Article table options:
  27801.  
  27802. +Scroll last selected article to top?   (YES/NO)%==>_Z  +
  27803. +Put cursor at last selected article?   (YES/NO)%==>_Z  +
  27804.  
  27805. +Number of heading rows to display per article  %==>_Z+  (Enter%1, 2+or%3+only)
  27806.  
  27807.  
  27808. +Press%ENTER+to change options.  Press%&END+(or type%END+command) when done.
  27809. )INIT
  27810.  .ZVARS  = '(NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS)'
  27811.  .HELP   = TNNMOPT
  27812.  .CURSOR = ZCMD
  27813.  &END = PFK(END)
  27814.  &ZCMD = &Z
  27815.  VGET (NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS) PROFILE
  27816.  &NNNGSCR  = TRANS(TRUNC(&NNNGSCR,1)  Y,YES N,NO *,YES)
  27817.  &NNNGCSR  = TRANS(TRUNC(&NNNGCSR,1)  Y,YES N,NO *,NO)
  27818.  &NNARSCR  = TRANS(TRUNC(&NNARSCR,1)  Y,YES N,NO *,YES)
  27819.  &NNARCSR  = TRANS(TRUNC(&NNARCSR,1)  Y,YES N,NO *,NO)
  27820.  &NNARROWS = TRANS(&NNARROWS 1,1 2,2 3,3 *,1)
  27821. )PROC
  27822.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  27823.  IF (.RESP = ENTER)
  27824.   &NNNGSCR  = TRUNC(&NNNGSCR,1)
  27825.   &NNNGCSR  = TRUNC(&NNNGCSR,1)
  27826.   &NNARSCR  = TRUNC(&NNARSCR,1)
  27827.   &NNARCSR  = TRUNC(&NNARCSR,1)
  27828.   VER(&NNNGSCR,NB,LIST,Y,N)
  27829.   VER(&NNNGCSR,NB,LIST,Y,N)
  27830.   VER(&NNARSCR,NB,LIST,Y,N)
  27831.   VER(&NNARCSR,NB,LIST,Y,N)
  27832.   VER(&NNARROWS,NB,LIST,1,2,3)
  27833.  VPUT (NNNGSCR NNNGCSR NNARSCR NNARCSR NNARROWS) PROFILE
  27834. )END
  27835. ./   ADD NAME=NNMPAUTH,SSI=01050017
  27836. )ATTR
  27837. /*                                                                   /*
  27838. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27839. /*                                                                   /*
  27840. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27841. /* including the implied warranties of merchantability and fitness,  /*
  27842. /* are expressly denied.                                             /*
  27843. /*                                                                   /*
  27844. /* Provided this copyright notice is included, this software may     /*
  27845. /* be freely distributed and not offered for sale.                   /*
  27846. /*                                                                   /*
  27847. /* Changes or modifications may be made and used only by the maker   /*
  27848. /* of same, and not further distributed.  Such modifications should  /*
  27849. /* be mailed to the author for consideration for addition to the     /*
  27850. /* software and incorporation in subsequent releases.                /*
  27851. /*                                                                   /*
  27852. )BODY WINDOW(62,14)
  27853. +
  27854. %Command ===>_ZCMD
  27855. +
  27856.  NNMVS could not obtain authorization from the NNTP server.
  27857.  You may proceed, but you should be aware that some news
  27858.  reading or posting operations may fail.
  27859.  
  27860.  The response from server &NNSERVER was:
  27861.  
  27862. %&NNSRVRSP
  27863. +
  27864.  Press%ENTER+to proceed.
  27865.  Press%END  +to return to the NNMVS primary menu.
  27866. )INIT
  27867.  .HELP = TNNM
  27868.  &ZWINTTL = 'Server authorization failed'
  27869.  &END = PFK(END)
  27870.  &ZCMD = &Z
  27871. )PROC
  27872.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  27873. )END
  27874. ./   ADD NAME=NNMPCAN,SSI=01000015
  27875. )ATTR
  27876. /*                                                                   /*
  27877. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27878. /*                                                                   /*
  27879. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27880. /* including the implied warranties of merchantability and fitness,  /*
  27881. /* are expressly denied.                                             /*
  27882. /*                                                                   /*
  27883. /* Provided this copyright notice is included, this software may     /*
  27884. /* be freely distributed and not offered for sale.                   /*
  27885. /*                                                                   /*
  27886. /* Changes or modifications may be made and used only by the maker   /*
  27887. /* of same, and not further distributed.  Such modifications should  /*
  27888. /* be mailed to the author for consideration for addition to the     /*
  27889. /* software and incorporation in subsequent releases.                /*
  27890. /*                                                                   /*
  27891.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  27892. )BODY WINDOW(64,14)
  27893. +
  27894. %Command ===>^ZCMD
  27895. +
  27896. +Newsgroup :%&NNCGROUP
  27897. +Article:   %&NNCNUM
  27898. +Message-ID:%&NNCMSGID
  27899. +Subject:   %&NNCSUBJ
  27900.  
  27901.  
  27902. +This action will forward a CANCEL request to the news server.
  27903. +
  27904. +Press%ENTER+to proceed to cancel this article.
  27905. +
  27906. +Press%&END (END)+to abandon the request and leave the article.
  27907. )INIT
  27908.  .HELP = TNNM
  27909.  &ZWINTTL = 'Confirm Article Cancellation'
  27910.  &END = PFK(END)
  27911. )PROC
  27912.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  27913. )END
  27914. ./   ADD NAME=NNMPCONM,SSI=01040055
  27915. )ATTR
  27916. /*                                                                   /*
  27917. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27918. /*                                                                   /*
  27919. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27920. /* including the implied warranties of merchantability and fitness,  /*
  27921. /* are expressly denied.                                             /*
  27922. /*                                                                   /*
  27923. /* Provided this copyright notice is included, this software may     /*
  27924. /* be freely distributed and not offered for sale.                   /*
  27925. /*                                                                   /*
  27926. /* Changes or modifications may be made and used only by the maker   /*
  27927. /* of same, and not further distributed.  Such modifications should  /*
  27928. /* be mailed to the author for consideration for addition to the     /*
  27929. /* software and incorporation in subsequent releases.                /*
  27930. /*                                                                   /*
  27931. )BODY WINDOW(49,10)
  27932. +
  27933. %Command ===>_ZCMD
  27934.  
  27935. +To:     %&NNMAILTO
  27936. +Subject:%&NNMAILSJ
  27937.  
  27938. +Press%ENTER     +to mail this message.
  27939. +Press%&END (END)+to return to the mail menu.
  27940. +Enter%CANCEL    +to cancel the message.
  27941. )INIT
  27942.  .HELP = TNNM
  27943.  &ZWINTTL = 'Confirm mailing'
  27944.  &END = PFK(END)
  27945.  &ZCMD = &Z
  27946. )PROC
  27947.  VER(&ZCMD,LIST,CAN,CANCEL)
  27948. )END
  27949. ./   ADD NAME=NNMPCONP,SSI=01040000
  27950. )ATTR
  27951. /*                                                                   /*
  27952. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27953. /*                                                                   /*
  27954. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27955. /* including the implied warranties of merchantability and fitness,  /*
  27956. /* are expressly denied.                                             /*
  27957. /*                                                                   /*
  27958. /* Provided this copyright notice is included, this software may     /*
  27959. /* be freely distributed and not offered for sale.                   /*
  27960. /*                                                                   /*
  27961. /* Changes or modifications may be made and used only by the maker   /*
  27962. /* of same, and not further distributed.  Such modifications should  /*
  27963. /* be mailed to the author for consideration for addition to the     /*
  27964. /* software and incorporation in subsequent releases.                /*
  27965. /*                                                                   /*
  27966. )BODY WINDOW(49,10)
  27967. +
  27968. %Command ===>_ZCMD
  27969.  
  27970. +Newsgroups:%&NNPOSTNG
  27971. +Subject:   %&NNPOSTSJ
  27972.  
  27973. +Press%ENTER     +to post this article.
  27974. +Press%&END (END)+to return to the posting menu.
  27975. +Enter%CANCEL    +to cancel the post.
  27976. )INIT
  27977.  .HELP = TNNM
  27978.  &ZWINTTL = 'Confirm posting'
  27979.  &END = PFK(END)
  27980.  &ZCMD = &Z
  27981. )PROC
  27982.  VER(&ZCMD,LIST,CAN,CANCEL)
  27983. )END
  27984. ./   ADD NAME=NNMPEXDS,SSI=01150041
  27985. )ATTR
  27986. /*                                                                   /*
  27987. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  27988. /*                                                                   /*
  27989. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  27990. /* including the implied warranties of merchantability and fitness,  /*
  27991. /* are expressly denied.                                             /*
  27992. /*                                                                   /*
  27993. /* Provided this copyright notice is included, this software may     /*
  27994. /* be freely distributed and not offered for sale.                   /*
  27995. /*                                                                   /*
  27996. /* Changes or modifications may be made and used only by the maker   /*
  27997. /* of same, and not further distributed.  Such modifications should  /*
  27998. /* be mailed to the author for consideration for addition to the     /*
  27999. /* software and incorporation in subsequent releases.                /*
  28000. /*                                                                   /*
  28001.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28002. )BODY WINDOW(77,16)
  28003. +
  28004. %Command ===>^ZCMD
  28005. +
  28006. +&NUMBER       %&SUBJECT
  28007. +
  28008. +Save to data set ===>_NNEXDSN
  28009. +Expand tab characters?       ===>_Z  +
  28010.  
  28011. +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
  28012.  
  28013. +Append to end of data set?   ===>_Z  +
  28014. +Blank line after separator?  ===>_Z  +
  28015. +Separator line between articles (append mode only...blank for none):
  28016. +>^Z                                                                       +<
  28017.  
  28018. +Press%&END (END)+to cancel the extract request.
  28019. )INIT
  28020.  .HELP = TNNM
  28021.  .ZVARS = '(NNEXTAB NNEXAPP NNEXBLK NNEXSEP)'
  28022.  .CURSOR = NNEXDSN
  28023.  IF (&NNTNUM ^= &Z)
  28024.   &ZWINTTL = 'Extract from &NNGROUP'
  28025.   &NUMBER  = 'Article &NNTNUM: '
  28026.   &SUBJECT = '&NNTSUBJ'
  28027.  ELSE
  28028.   &ZWINTTL = 'Extract text'
  28029.   &NUMBER  = ' '
  28030.   &SUBJECT = ' '
  28031.  &END = PFK(END)
  28032.  &ZCMD = &Z
  28033.  VGET (NNEXDSN NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28034.  &NNEXTAB = TRANS(&NNEXTAB Y,YES N,NO ' ',NO)
  28035.  &NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
  28036.  &NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
  28037. )PROC
  28038.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28039.  VER(&NNEXDSN,NB,DSNAME)
  28040.  &NNEXTAB = TRUNC(&NNEXTAB,1)
  28041.  VER(&NNEXTAB,NB,LIST,Y,N)
  28042.  &NNEXAPP = TRUNC(&NNEXAPP,1)
  28043.  VER(&NNEXAPP,NB,LIST,Y,N)
  28044.  &NNEXBLK = TRUNC(&NNEXBLK,1)
  28045.  VER(&NNEXBLK,NB,LIST,Y,N)
  28046.  VPUT (NNEXDSN NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28047. )END
  28048. ./   ADD NAME=NNMPEXNG,SSI=01040050
  28049. )ATTR
  28050. /*                                                                   /*
  28051. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28052. /*                                                                   /*
  28053. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28054. /* including the implied warranties of merchantability and fitness,  /*
  28055. /* are expressly denied.                                             /*
  28056. /*                                                                   /*
  28057. /* Provided this copyright notice is included, this software may     /*
  28058. /* be freely distributed and not offered for sale.                   /*
  28059. /*                                                                   /*
  28060. /* Changes or modifications may be made and used only by the maker   /*
  28061. /* of same, and not further distributed.  Such modifications should  /*
  28062. /* be mailed to the author for consideration for addition to the     /*
  28063. /* software and incorporation in subsequent releases.                /*
  28064. /*                                                                   /*
  28065.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28066. )BODY WINDOW(77,14)
  28067. +
  28068. %Command ===>^ZCMD
  28069. +
  28070. +Save to data set ===>_NNEXDSN
  28071.  
  28072. +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
  28073.  
  28074. +Append to end of data set?   ===>_Z  +
  28075. +Blank line after separator?  ===>_Z  +
  28076. +Separator line between articles (append mode only...blank for none):
  28077. +>^Z                                                                       +<
  28078.  
  28079. +Press%&END (END)+to cancel the extract request.
  28080. )INIT
  28081.  .HELP = TNNM
  28082.  .ZVARS = '(NNEXAPP NNEXBLK NNEXSEP)'
  28083.  .CURSOR = NNEXDSN
  28084.  &ZWINTTL = 'Extract newsgroup listing'
  28085.  &END = PFK(END)
  28086.  &ZCMD = &Z
  28087.  VGET (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28088.  &NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
  28089.  &NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
  28090. )PROC
  28091.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28092.  VER(&NNEXDSN,NB,DSNAME)
  28093.  &NNEXAPP = TRUNC(&NNEXAPP,1)
  28094.  VER(&NNEXAPP,NB,LIST,Y,N)
  28095.  &NNEXBLK = TRUNC(&NNEXBLK,1)
  28096.  VER(&NNEXBLK,NB,LIST,Y,N)
  28097.  VPUT (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28098. )END
  28099. ./   ADD NAME=NNMPEXNP,SSI=01060057
  28100. )ATTR
  28101. /*                                                                   /*
  28102. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28103. /*                                                                   /*
  28104. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28105. /* including the implied warranties of merchantability and fitness,  /*
  28106. /* are expressly denied.                                             /*
  28107. /*                                                                   /*
  28108. /* Provided this copyright notice is included, this software may     /*
  28109. /* be freely distributed and not offered for sale.                   /*
  28110. /*                                                                   /*
  28111. /* Changes or modifications may be made and used only by the maker   /*
  28112. /* of same, and not further distributed.  Such modifications should  /*
  28113. /* be mailed to the author for consideration for addition to the     /*
  28114. /* software and incorporation in subsequent releases.                /*
  28115. /*                                                                   /*
  28116.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28117. )BODY EXPAND(``) WINDOW(77,14)
  28118. +
  28119. %Command ===>^ZCMD
  28120. +
  28121. +Data set name%===>_NNEXPDS
  28122. +Member prefix%===>_NNEXPMP + (article number appended - default is%#+)
  28123.  
  28124. +Note: The dataset must be a PDS (old or new) with RECFM=VB and LRECL=259.
  28125.  
  28126. +Expand tab characters?      %===>_Z  +
  28127.  
  28128. +From article number%===>_NNEXAN1      + (blank for first article in table)
  28129. +To   article number%===>_NNEXAN2      + (blank for last article in table)
  28130.  
  28131. +Press%&END (END)+to cancel the extract request.
  28132. )INIT
  28133.  .HELP = TNNM
  28134.  .ZVARS = '(NNEXTAB)'
  28135.  .CURSOR = ZCMD
  28136.  &ZWINTTL = 'Log text of articles in &NNGROUP to PDS members'
  28137.  &NUMBER = ' &NNTNUM: '
  28138.  &END = PFK(END)
  28139.  &ZCMD = &Z
  28140.  VGET (NNEXPDS NNEXPMP NNEXTAB) PROFILE
  28141.  &NNEXTAB = TRANS(&NNEXTAB Y,YES N,NO ' ',NO)
  28142.  IF (&NNEXPMP = &Z) &NNEXPMP = '#'
  28143.  &NNEXAN1 = &Z
  28144.  &NNEXAN2 = &Z
  28145. )PROC
  28146.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28147.  &NNEXTAB = TRUNC(&NNEXTAB,1)
  28148.  VER(&NNEXTAB,NB,LIST,Y,N)
  28149.  VER(&NNEXPDS,NB,DSNAME)
  28150.  &TEMP1 = TRUNC(&NNEXPDS,1)
  28151.  &TEMP2 = .TRAIL
  28152.  IF (&TEMP1 = '''')
  28153.   &NNEXDSN = TRUNC(&TEMP2,'''')
  28154.  ELSE
  28155.   &NNEXDSN = '&ZPREFIX..&NNEXPDS'
  28156.   VER(&NNEXPMP,NB,NAME)
  28157.  VER(&NNEXAN1,NUM)
  28158.  VER(&NNEXAN2,NUM)
  28159.  VPUT (NNEXPDS NNEXPMP NNEXTAB) PROFILE
  28160. )END
  28161. ./   ADD NAME=NNMPEXNS,SSI=01050005
  28162. )ATTR
  28163. /*                                                                   /*
  28164. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28165. /*                                                                   /*
  28166. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28167. /* including the implied warranties of merchantability and fitness,  /*
  28168. /* are expressly denied.                                             /*
  28169. /*                                                                   /*
  28170. /* Provided this copyright notice is included, this software may     /*
  28171. /* be freely distributed and not offered for sale.                   /*
  28172. /*                                                                   /*
  28173. /* Changes or modifications may be made and used only by the maker   /*
  28174. /* of same, and not further distributed.  Such modifications should  /*
  28175. /* be mailed to the author for consideration for addition to the     /*
  28176. /* software and incorporation in subsequent releases.                /*
  28177. /*                                                                   /*
  28178.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28179. )BODY EXPAND(``) WINDOW(77,17)
  28180. +
  28181. %Command ===>^ZCMD
  28182. +
  28183. +Data set name%===>_NNEXSEQ
  28184. +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
  28185. +
  28186. +Expand tab characters?      %===>_Z  +
  28187. +
  28188. +Append to end of data set?  %===>_Z  +
  28189. +Blank line after separator? %===>_Z  +
  28190. +Separator line before each article (leave blank for none):
  28191. +>^Z                                                                       +<
  28192.  
  28193. +From article number%===>_NNEXAN1      + (blank for first article in table)
  28194. +To   article number%===>_NNEXAN2      + (blank for last article in table)
  28195.  
  28196. +Press%&END (END)+to cancel the extract request.
  28197. )INIT
  28198.  .HELP = TNNM
  28199.  .ZVARS = '(NNEXTAB NNEXAPP NNEXBLK NNEXSEP)'
  28200.  .CURSOR = ZCMD
  28201.  &ZWINTTL = 'Log text of articles in &NNGROUP to sequential file'
  28202.  &NUMBER = ' &NNTNUM: '
  28203.  &END = PFK(END)
  28204.  &ZCMD = &Z
  28205.  VGET (NNEXSEQ NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28206.  &NNEXTAB = TRANS(&NNEXTAB Y,YES N,NO ' ',NO)
  28207.  &NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
  28208.  &NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
  28209.  &NNEXAN1 = &Z
  28210.  &NNEXAN2 = &Z
  28211. )PROC
  28212.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28213.  VER(&NNEXSEQ,NB,DSNAME)
  28214.  &NNEXDSN = &NNEXSEQ
  28215.  &NNEXTAB = TRUNC(&NNEXTAB,1)
  28216.  VER(&NNEXTAB,NB,LIST,Y,N)
  28217.  &NNEXAPP = TRUNC(&NNEXAPP,1)
  28218.  VER(&NNEXAPP,NB,LIST,Y,N)
  28219.  &NNEXBLK = TRUNC(&NNEXBLK,1)
  28220.  VER(&NNEXBLK,NB,LIST,Y,N)
  28221.  VER(&NNEXAN1,NUM)
  28222.  VER(&NNEXAN2,NUM)
  28223.  VPUT (NNEXSEQ NNEXTAB NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28224. )END
  28225. ./   ADD NAME=NNMPEXNT,SSI=01060013
  28226. )ATTR
  28227. /*                                                                   /*
  28228. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28229. /*                                                                   /*
  28230. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28231. /* including the implied warranties of merchantability and fitness,  /*
  28232. /* are expressly denied.                                             /*
  28233. /*                                                                   /*
  28234. /* Provided this copyright notice is included, this software may     /*
  28235. /* be freely distributed and not offered for sale.                   /*
  28236. /*                                                                   /*
  28237. /* Changes or modifications may be made and used only by the maker   /*
  28238. /* of same, and not further distributed.  Such modifications should  /*
  28239. /* be mailed to the author for consideration for addition to the     /*
  28240. /* software and incorporation in subsequent releases.                /*
  28241. /*                                                                   /*
  28242.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28243. )BODY WINDOW(77,10)
  28244. +
  28245. %Command ===>^ZCMD
  28246. +
  28247. +Move cursor to choice (or type%S+next to choice) and press%ENTER+to select:
  28248. +
  28249. _A%1+- List%titles+of articles in table
  28250. _B%2+- Log %text  +of articles to%sequential file+
  28251. _C%3+- Log %text  +of articles to%members of PDS+
  28252. +
  28253. +Press%&END (END)+to cancel the extract request.
  28254. )INIT
  28255.  .HELP = TNNM
  28256.  .CURSOR = ZCMD
  28257.  &ZWINTTL = 'Extract news articles - titles or text'
  28258.  &END = PFK(END)
  28259.  &ZCMD = &Z
  28260.  &A = &Z 
  28261.  &B = &Z 
  28262.  &C = &Z 
  28263. )PROC
  28264.  VER(&ZCMD,LIST,1,2,3)
  28265.  IF (&ZCMD ^= &Z)
  28266.   &NNCHOICE = TRANS(&ZCMD 1 1 2 2 3 3 * ?)
  28267.  ELSE
  28268.   &TEMP = '&A/&B/&C'
  28269.   IF (&TEMP = '//')
  28270.    &NNCHOICE = TRANS(.CURSOR A 1 B 2 C 3 * ?)
  28271.   ELSE
  28272.    &NNCHOICE = TRANS(&TEMP  'S//' 1
  28273.                             '1//' 1
  28274.                             '/S/' 2
  28275.                             '/2/' 2
  28276.                             '//S' 3
  28277.                             '//3' 3
  28278.                                * ?
  28279.                    )
  28280. )END
  28281. ./   ADD NAME=NNMPEXN1,SSI=01030021
  28282. )ATTR
  28283. /*                                                                   /*
  28284. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28285. /*                                                                   /*
  28286. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28287. /* including the implied warranties of merchantability and fitness,  /*
  28288. /* are expressly denied.                                             /*
  28289. /*                                                                   /*
  28290. /* Provided this copyright notice is included, this software may     /*
  28291. /* be freely distributed and not offered for sale.                   /*
  28292. /*                                                                   /*
  28293. /* Changes or modifications may be made and used only by the maker   /*
  28294. /* of same, and not further distributed.  Such modifications should  /*
  28295. /* be mailed to the author for consideration for addition to the     /*
  28296. /* software and incorporation in subsequent releases.                /*
  28297. /*                                                                   /*
  28298.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28299. )BODY WINDOW(77,14)
  28300. +
  28301. %Command ===>^ZCMD
  28302. +
  28303. +Save to data set ===>_NNEXDSN
  28304.  
  28305. +(Note: Data set will be RECFM=VB, LRECL=259, BLKSIZE=6233.)
  28306.  
  28307. +Append to end of data set?   ===>_Z  +
  28308. +Blank line after separator?  ===>_Z  +
  28309. +Separator line between articles (append mode only...blank for none):
  28310. +>^Z                                                                       +<
  28311.  
  28312. +Press%&END (END)+to cancel the extract request.
  28313. )INIT
  28314.  .HELP = TNNM
  28315.  .ZVARS = '(NNEXAPP NNEXBLK NNEXSEP)'
  28316.  .CURSOR = NNEXDSN
  28317.  &ZWINTTL = 'Extract news article listing'
  28318.  &END = PFK(END)
  28319.  &ZCMD = &Z
  28320.  VGET (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28321.  &NNEXAPP = TRANS(&NNEXAPP Y,YES N,NO ' ',NO)
  28322.  &NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
  28323. )PROC
  28324.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28325.  VER(&NNEXDSN,NB,DSNAME)
  28326.  &NNEXAPP = TRUNC(&NNEXAPP,1)
  28327.  VER(&NNEXAPP,NB,LIST,Y,N)
  28328.  &NNEXBLK = TRUNC(&NNEXBLK,1)
  28329.  VER(&NNEXBLK,NB,LIST,Y,N)
  28330.  VPUT (NNEXDSN NNEXAPP NNEXBLK NNEXSEP) PROFILE
  28331. )END
  28332. ./   ADD NAME=NNMPEXOW,SSI=01020028
  28333. )ATTR
  28334. /*                                                                   /*
  28335. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28336. /*                                                                   /*
  28337. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28338. /* including the implied warranties of merchantability and fitness,  /*
  28339. /* are expressly denied.                                             /*
  28340. /*                                                                   /*
  28341. /* Provided this copyright notice is included, this software may     /*
  28342. /* be freely distributed and not offered for sale.                   /*
  28343. /*                                                                   /*
  28344. /* Changes or modifications may be made and used only by the maker   /*
  28345. /* of same, and not further distributed.  Such modifications should  /*
  28346. /* be mailed to the author for consideration for addition to the     /*
  28347. /* software and incorporation in subsequent releases.                /*
  28348. /*                                                                   /*
  28349.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28350. )BODY WINDOW(58,10)
  28351. +
  28352. %Command ===>^ZCMD
  28353. +
  28354. +Dataset already exists:
  28355. +
  28356. %&NNEXDSN
  28357. +
  28358. +Press%ENTER+to%&ACTION
  28359. +Press%&END (END)+to cancel the request.
  28360. +
  28361. )INIT
  28362.  .HELP = TNNM
  28363.  .ALARM = YES
  28364.  &ZWINTTL = 'Extract To Existing Data Set'
  28365.  &END = PFK(END)
  28366.  &APP = TRUNC(&NNEXAPP,1)
  28367.  IF (&APP = Y) &ACTION = 'append to the end of the data set.'
  28368.  ELSE          &ACTION = 'overwrite the current data set.'
  28369. )PROC
  28370.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28371. )END
  28372. ./   ADD NAME=NNMPEXPW,SSI=01020035
  28373. )ATTR
  28374. /*                                                                   /*
  28375. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28376. /*                                                                   /*
  28377. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28378. /* including the implied warranties of merchantability and fitness,  /*
  28379. /* are expressly denied.                                             /*
  28380. /*                                                                   /*
  28381. /* Provided this copyright notice is included, this software may     /*
  28382. /* be freely distributed and not offered for sale.                   /*
  28383. /*                                                                   /*
  28384. /* Changes or modifications may be made and used only by the maker   /*
  28385. /* of same, and not further distributed.  Such modifications should  /*
  28386. /* be mailed to the author for consideration for addition to the     /*
  28387. /* software and incorporation in subsequent releases.                /*
  28388. /*                                                                   /*
  28389.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28390. )BODY WINDOW(58,13)
  28391. +
  28392. %Command ===>^ZCMD
  28393. +
  28394. +Partitioned dataset already exists:
  28395. +
  28396. %&NNEXDSN
  28397. +
  28398. +If member names are generated that match existing members
  28399. +of this PDS, they will be%overwritten.+
  28400. +
  28401. +Press%ENTER+to proceed to use this PDS.
  28402. +Press%&END (END)+to cancel the request.
  28403. +
  28404. )INIT
  28405.  .HELP = TNNM
  28406.  .ALARM = YES
  28407.  &ZWINTTL = 'Extract To Members of Existing PDS'
  28408.  &END = PFK(END)
  28409. )PROC
  28410.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28411. )END
  28412. ./   ADD NAME=NNMPGAUT,SSI=01010012
  28413. )ATTR
  28414. /*                                                                   /*
  28415. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28416. /*                                                                   /*
  28417. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28418. /* including the implied warranties of merchantability and fitness,  /*
  28419. /* are expressly denied.                                             /*
  28420. /*                                                                   /*
  28421. /* Provided this copyright notice is included, this software may     /*
  28422. /* be freely distributed and not offered for sale.                   /*
  28423. /*                                                                   /*
  28424. /* Changes or modifications may be made and used only by the maker   /*
  28425. /* of same, and not further distributed.  Such modifications should  /*
  28426. /* be mailed to the author for consideration for addition to the     /*
  28427. /* software and incorporation in subsequent releases.                /*
  28428. /*                                                                   /*
  28429.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28430.        @   TYPE(INPUT) INTENS(NON)  CAPS(OFF) JUST(LEFT)
  28431. )BODY WINDOW(64,14)
  28432. +
  28433. %Command ===>^ZCMD
  28434. +
  28435. +The NNTP server at &NNSERVER
  28436. +requires authorization to perform this operation.
  28437. +
  28438. +Username (as known to NNTP server) ===>^NNAUSER
  28439. +Password (as known to NNTP server) ===>@NNAPASS
  28440. +
  28441.  
  28442. +Press%&END (END)+to abort the current request.
  28443. )INIT
  28444.  .HELP = TNNM
  28445.  &ZWINTTL = 'Server Authorization Required'
  28446.  &NNAPASS = &Z
  28447.  &END = PFK(END)
  28448. )PROC
  28449.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28450.  VER(&NNAUSER,NB)
  28451.  VER(&NNAPASS,NB)
  28452.  VPUT (NNAUSER) PROFILE
  28453. )END
  28454. ./   ADD NAME=NNMPGREG,SSI=01060042
  28455. )ATTR
  28456. /*                                                                   /*
  28457. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28458. /*                                                                   /*
  28459. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28460. /* including the implied warranties of merchantability and fitness,  /*
  28461. /* are expressly denied.                                             /*
  28462. /*                                                                   /*
  28463. /* Provided this copyright notice is included, this software may     /*
  28464. /* be freely distributed and not offered for sale.                   /*
  28465. /*                                                                   /*
  28466. /* Changes or modifications may be made and used only by the maker   /*
  28467. /* of same, and not further distributed.  Such modifications should  /*
  28468. /* be mailed to the author for consideration for addition to the     /*
  28469. /* software and incorporation in subsequent releases.                /*
  28470. /*                                                                   /*
  28471.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28472. )BODY WINDOW(58,10)
  28473. +
  28474. %Command ===>^ZCMD
  28475. +
  28476. +Get current status of each newsgroup in your list?
  28477. +(If you answer YES, it will take longer to start up.)
  28478. +(If you answer NO, displayed status will be incomplete.)
  28479. +
  28480. %===>_Z  +
  28481.  
  28482. +Press%&END (END)+to return to the previous panel.
  28483. )INIT
  28484.  .HELP = TNNM
  28485.  .ZVARS = '(NNRGANS)'
  28486.  .CURSOR = NNRGANS
  28487.  &ZWINTTL = ''
  28488.  &END = PFK(END)
  28489.  &NNRGANS = Y
  28490. )PROC
  28491.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28492.  &NNRGANS = TRUNC(&NNRGANS,1)
  28493.  VER(&NNRGANS,NB,LIST,Y,N)
  28494. )END
  28495. ./   ADD NAME=NNMPMALL,SSI=01010044
  28496. )ATTR
  28497. /*                                                                   /*
  28498. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28499. /*                                                                   /*
  28500. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28501. /* including the implied warranties of merchantability and fitness,  /*
  28502. /* are expressly denied.                                             /*
  28503. /*                                                                   /*
  28504. /* Provided this copyright notice is included, this software may     /*
  28505. /* be freely distributed and not offered for sale.                   /*
  28506. /*                                                                   /*
  28507. /* Changes or modifications may be made and used only by the maker   /*
  28508. /* of same, and not further distributed.  Such modifications should  /*
  28509. /* be mailed to the author for consideration for addition to the     /*
  28510. /* software and incorporation in subsequent releases.                /*
  28511. /*                                                                   /*
  28512.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28513. )BODY WINDOW(76,14)
  28514. +
  28515. %Command ===>^ZCMD
  28516. +
  28517. +Newsgroup:%&NNGNAME
  28518. +
  28519. +What exactly do you want to do?
  28520. +
  28521. _Z%*+Mark%all+articles in the newsgroup &NNMARK
  28522. _Z%*+Mark%currently displayed+articles &NNMARK
  28523. _Z%*+Cancel this request and return to previous panel
  28524.  
  28525. +Move cursor to choice (or type%S+next to choice) and press%ENTER+to do it.
  28526. +
  28527. +Press%&END (END)+to cancel the request.
  28528. )INIT
  28529.  .HELP = TNNM
  28530.  .ZVARS = '(S1 S2 S3)'
  28531.  .CURSOR = ZCMD
  28532.  &ZWINTTL = 'Confirm Marking All Articles in Newsgroup'
  28533.  &END = PFK(END)
  28534.  &ZCMD = &Z
  28535.  &S1   = &Z
  28536.  &S2   = &Z
  28537.  &S3   = &Z
  28538. )PROC
  28539.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28540.  &TEMP = '&S1/&S2/&S3'
  28541.  IF (&TEMP = '//')
  28542.   &NNCHOICE = TRANS(.CURSOR S1 1 S2 2 S3 3 * ?)
  28543.  ELSE
  28544.   &NNCHOICE = TRANS(&TEMP  'S//' 1
  28545.                            '1//' 1
  28546.                            '/S/' 2
  28547.                            '/2/' 2
  28548.                            '//S' 3
  28549.                            '//3' 3
  28550.                                * ?
  28551.                   )
  28552. )END
  28553. ./   ADD NAME=NNMPMARK,SSI=01030048
  28554. )ATTR
  28555. /*                                                                   /*
  28556. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28557. /*                                                                   /*
  28558. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28559. /* including the implied warranties of merchantability and fitness,  /*
  28560. /* are expressly denied.                                             /*
  28561. /*                                                                   /*
  28562. /* Provided this copyright notice is included, this software may     /*
  28563. /* be freely distributed and not offered for sale.                   /*
  28564. /*                                                                   /*
  28565. /* Changes or modifications may be made and used only by the maker   /*
  28566. /* of same, and not further distributed.  Such modifications should  /*
  28567. /* be mailed to the author for consideration for addition to the     /*
  28568. /* software and incorporation in subsequent releases.                /*
  28569. /*                                                                   /*
  28570.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28571. )BODY WINDOW(58,10)
  28572. +
  28573. %Command ===>^ZCMD
  28574. +
  28575. +Newsgroup:%&NNGNAME
  28576. +
  28577. +Be sure you really want to mark all articles%&NNMARK..
  28578. +
  28579. +Press%ENTER+to proceed with marking all articles.
  28580. +
  28581. +Press%&END (END)+to cancel the request.
  28582. )INIT
  28583.  .HELP = TNNM
  28584.  &ZWINTTL = 'Confirm Marking All Articles in Newsgroup'
  28585.  &END = PFK(END)
  28586. )PROC
  28587.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28588. )END
  28589. ./   ADD NAME=NNMPOPT,SSI=01050056
  28590. )ATTR
  28591. /*                                                                   /*
  28592. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28593. /*                                                                   /*
  28594. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28595. /* including the implied warranties of merchantability and fitness,  /*
  28596. /* are expressly denied.                                             /*
  28597. /*                                                                   /*
  28598. /* Provided this copyright notice is included, this software may     /*
  28599. /* be freely distributed and not offered for sale.                   /*
  28600. /*                                                                   /*
  28601. /* Changes or modifications may be made and used only by the maker   /*
  28602. /* of same, and not further distributed.  Such modifications should  /*
  28603. /* be mailed to the author for consideration for addition to the     /*
  28604. /* software and incorporation in subsequent releases.                /*
  28605. /*                                                                   /*
  28606.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28607. )BODY WINDOW(77,11)
  28608. +
  28609. %Command ===>^ZCMD
  28610. +
  28611. +Move cursor to choice (or type%S+next to choice) and press%ENTER+to select:
  28612. +
  28613. _Z%1+- RFC822 header display options
  28614. _Z%2+- Article retrieval options
  28615. _Z%3+- Table processing options
  28616. +
  28617. +Press%&END (END)+to return to the previous panel.
  28618. )INIT
  28619.  .HELP = TNNMOPT
  28620.  .ZVARS = '(S1 S2 S3)'
  28621.  .CURSOR = ZCMD
  28622.  &ZWINTTL = 'Customize user options'
  28623.  &END = PFK(END)
  28624.  &ZCMD = &Z
  28625.  &S1   = &Z
  28626.  &S2   = &Z
  28627.  &S3   = &Z
  28628. )PROC
  28629.  IF (&ZCMD ^= &Z)
  28630.   &NNCHOICE = TRANS(&ZCMD 1 1 2 2 3 3 * ?)
  28631.  ELSE
  28632.   &TEMP = '&S1/&S2/&S3'
  28633.   IF (&TEMP = '//')
  28634.    &NNCHOICE = TRANS(.CURSOR S1 1 S2 2 S3 3 * ?)
  28635.   ELSE
  28636.    &NNCHOICE = TRANS(&TEMP  'S//' 1
  28637.                             '1//' 1
  28638.                             '/S/' 2
  28639.                             '/2/' 2
  28640.                             '//S' 3
  28641.                             '//3' 3
  28642.                                 * ?
  28643.                    )
  28644. )END
  28645. ./   ADD NAME=NNMPPRNT,SSI=01010028
  28646. )ATTR
  28647. /*                                                                   /*
  28648. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     /*
  28649. /*                                                                   /*
  28650. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28651. /* including the implied warranties of merchantability and fitness,  /*
  28652. /* are expressly denied.                                             /*
  28653. /*                                                                   /*
  28654. /* Provided this copyright notice is included, this software may     /*
  28655. /* be freely distributed and not offered for sale.                   /*
  28656. /*                                                                   /*
  28657. /* Changes or modifications may be made and used only by the maker   /*
  28658. /* of same, and not further distributed.  Such modifications should  /*
  28659. /* be mailed to the author for consideration for addition to the     /*
  28660. /* software and incorporation in subsequent releases.                /*
  28661. /*                                                                   /*
  28662.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28663. )BODY WINDOW(77,9)
  28664. +
  28665. %Command ===>^ZCMD
  28666. +
  28667. +Move cursor to choice (or type%S+next to choice) and press%ENTER+to select:
  28668. +
  28669. _A%1+- Print%titles+of articles in table
  28670. _B%2+- Print%text  +of articles
  28671. +
  28672. +Press%&END (END)+to cancel the print request.
  28673. )INIT
  28674.  .HELP = TNNM
  28675.  .CURSOR = ZCMD
  28676.  &ZWINTTL = 'Print news articles - titles or text'
  28677.  &END = PFK(END)
  28678.  &ZCMD = &Z
  28679.  &A = &Z 
  28680.  &B = &Z 
  28681. )PROC
  28682.  VER(&ZCMD,LIST,1,2)
  28683.  IF (&ZCMD ^= &Z)
  28684.   &NNCHOICE = TRANS(&ZCMD 1 1 2 2 * ?)
  28685.  ELSE
  28686.   &TEMP = '&A/&B'
  28687.   IF (&TEMP = '/')
  28688.    &NNCHOICE = TRANS(.CURSOR A 1 B 2 * ?)
  28689.   ELSE
  28690.    &NNCHOICE = TRANS(&TEMP  'S/' 1
  28691.                             '1/' 1
  28692.                             '/S' 2
  28693.                             '/2' 2
  28694.                               * ?
  28695.                    )
  28696. )END
  28697. ./   ADD NAME=NNMPPRT,SSI=01050002
  28698. )ATTR
  28699. /*                                                                   /*
  28700. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28701. /*                                                                   /*
  28702. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  28703. /*                                                                   /*
  28704. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28705. /* including the implied warranties of merchantability and fitness,  /*
  28706. /* are expressly denied.                                             /*
  28707. /*                                                                   /*
  28708. /* Provided this copyright notice is included, this software may     /*
  28709. /* be freely distributed and not offered for sale.                   /*
  28710. /*                                                                   /*
  28711. /* Changes or modifications may be made and used only by the maker   /*
  28712. /* of same, and not further distributed.  Such modifications should  /*
  28713. /* be mailed to the author for consideration for addition to the     /*
  28714. /* software and incorporation in subsequent releases.                /*
  28715. /*                                                                   /*
  28716.  ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28717.  ~   TYPE(TEXT)  INTENS(HIGH)
  28718.  \   TYPE(TEXT)  INTENS(LOW)
  28719.  {   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28720.  }   TYPE(INPUT) INTENS(HIGH) CAPS(ON)  JUST(LEFT)
  28721.  #   TYPE(TEXT)  INTENS(LOW)
  28722.  @   TYPE(INPUT) INTENS(HIGH) CAPS(ON)  JUST(LEFT)
  28723. )BODY WINDOW(77,19)
  28724. +
  28725. %Command ===>^ZCMD
  28726. +
  28727. +&NUMBER       %&SUBJECT
  28728. +
  28729. +SYSOUT class ===>_Z+   Number of copies ===>_Z  +
  28730. #Destination  ===>@Z       #  Forms ===>@Z   #   UCS ===>@Z   +
  28731.  
  28732. +(Note: Print data will be released to SYSOUT immediately.)
  28733. +
  28734. \Page eject between articles?     ~===>}Z  +
  28735. \Blank line after separator?      ~===>}Z  +
  28736. \Separator line before each article (leave blank for none):
  28737. \>{Z                                                                       \<
  28738.  
  28739. \From article number~===>}NNEXAN1      \ (blank for first article in table)
  28740. \To   article number~===>}NNEXAN2      \ (blank for last article in table)
  28741.  
  28742. +Press%&END (END)+to cancel the print request.
  28743. )INIT
  28744.  .HELP = TNNM
  28745.  .ZVARS =
  28746.    '(NNEXSCL NNEXSCO NNEXSDE NNEXSFO NNEXSUC NNEXSPA NNEXBLK NNEXSEP)'
  28747.  .CURSOR = NNEXSCL
  28748.  &END = PFK(END)
  28749.  &ZCMD = &Z
  28750.  &NNEXSCO = 1
  28751.  &PVARS = 'NNEXSCL'
  28752.  IF (&NNALLPR ^= &Z)
  28753.   &PVARS = '&PVARS NNEXSDE NNEXSFO NNEXSUC'
  28754.   .ATTRCHAR('#') = 'TYPE(TEXT)   INTENS(LOW)'
  28755.   .ATTRCHAR('@') = 'TYPE(INPUT)  INTENS(HIGH) CAPS(ON)  JUST(LEFT)'
  28756.  ELSE
  28757.   .ATTRCHAR('#') = 'TYPE(TEXT)   INTENS(NON)'
  28758.   .ATTRCHAR('@') = 'TYPE(OUTPUT) INTENS(NON)'
  28759.  IF (&NNWHICH = NNMPPRNS)
  28760.   .ATTRCHAR('~') = 'TYPE(TEXT)   INTENS(HIGH)'
  28761.   .ATTRCHAR('\') = 'TYPE(TEXT)   INTENS(LOW)'
  28762.   .ATTRCHAR('{') = 'TYPE(INPUT)  INTENS(HIGH) CAPS(OFF) JUST(LEFT)'
  28763.   .ATTRCHAR('}') = 'TYPE(INPUT)  INTENS(HIGH) CAPS(ON)  JUST(LEFT)'
  28764.  ELSE
  28765.   .ATTRCHAR('~') = 'TYPE(TEXT)   INTENS(NON)'
  28766.   .ATTRCHAR('\') = 'TYPE(TEXT)   INTENS(NON)'
  28767.   .ATTRCHAR('{') = 'TYPE(OUTPUT) INTENS(NON)'
  28768.   .ATTRCHAR('}') = 'TYPE(OUTPUT) INTENS(NON)'
  28769.  IF (&NNWHICH = NNMPPRNG)
  28770.   &ZWINTTL = 'Print newsgroup listing'
  28771.  IF (&NNWHICH = NNMPPRN1)
  28772.   &ZWINTTL = 'Print news article listing'
  28773.  IF (&NNWHICH = NNMPPRDS)
  28774.   IF (&NNTNUM ^= &Z)
  28775.    &ZWINTTL = 'Print from &NNGROUP'
  28776.    &NUMBER  = 'Article &NNTNUM: '
  28777.    &SUBJECT = '&NNTSUBJ'
  28778.   ELSE
  28779.    &ZWINTTL = 'Print text'
  28780.    &NUMBER  = &Z
  28781.    &SUBJECT = &Z
  28782.  ELSE
  28783.   &NUMBER  = &Z
  28784.   &SUBJECT = &Z
  28785.  IF (&NNWHICH = NNMPPRNS)
  28786.   &PVARS = '&PVARS NNEXSPA NNEXBLK NNEXSEP'
  28787.   &ZWINTTL = 'Print text of articles in &NNGROUP'
  28788.   &NNEXSPA = TRANS(TRUNC(&NNEXSPA,1) Y,YES N,NO ' ',NO)
  28789.   &NNEXBLK = TRANS(TRUNC(&NNEXBLK,1) Y,YES N,NO ' ',NO)
  28790.   &NNEXSCO = 1
  28791.   &NNEXAN1 = &Z
  28792.   &NNEXAN2 = &Z
  28793.  VGET (&PVARS) PROFILE
  28794. )PROC
  28795.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28796.  VER(&NNEXSCL,NB)
  28797.  IF (&NNEXSCO = &Z) &NNEXSCO = 1
  28798.  VER(&NNEXSCO,NUM)
  28799.  VER(&NNEXSCO,RANGE,1,255)
  28800.  IF (&NNWHICH = NNMPPRNS)
  28801.   &NNEXSPA = TRUNC(&NNEXSPA,1)
  28802.   &NNEXBLK = TRUNC(&NNEXBLK,1)
  28803.   VER(&NNEXSPA,NB,LIST,Y,N)
  28804.   VER(&NNEXBLK,NB,LIST,Y,N)
  28805.   VER(&NNEXAN1,NUM)
  28806.   VER(&NNEXAN2,NUM)
  28807.  VPUT (&PVARS) PROFILE
  28808. )END
  28809. ./   ADD NAME=NNMQMAIL,SSI=01080000
  28810. )ATTR
  28811. /*                                                                   /*
  28812. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28813. /*                                                                   /*
  28814. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28815. /* including the implied warranties of merchantability and fitness,  /*
  28816. /* are expressly denied.                                             /*
  28817. /*                                                                   /*
  28818. /* Provided this copyright notice is included, this software may     /*
  28819. /* be freely distributed and not offered for sale.                   /*
  28820. /*                                                                   /*
  28821. /* Changes or modifications may be made and used only by the maker   /*
  28822. /* of same, and not further distributed.  Such modifications should  /*
  28823. /* be mailed to the author for consideration for addition to the     /*
  28824. /* software and incorporation in subsequent releases.                /*
  28825. /*                                                                   /*
  28826.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28827. )BODY EXPAND(``)
  28828. -`-`- Send a mail message or reply -`-`-
  28829. %Command ===>^ZCMD
  28830. +
  28831. %Note:+This sends private mail to the individual sender named below.
  28832.       +To transmit to the newsgroup, use the%POST+command, or use
  28833.       +the%F (FOLLOWUP)+selection code.+
  28834. +
  28835. +&HEADING
  28836.  
  28837. %Required Header Fields+
  28838.  
  28839. +Mail to ===>^NNMAILTO
  28840. +Subject ===>^NNMAILSJ
  28841.  
  28842. %Optional Header Fields+
  28843.  
  28844. +Reply to ==>^NNMAILRT
  28845.  
  28846. +Your human name ==>^NNMAILFR
  28847. +Signature file  ==>_NNMAILSF
  28848. +Edit profile    ==>_NNEDPROF+
  28849.  
  28850. +Press%ENTER+to proceed to the editor to compose the message.
  28851. +Press%&END (END)+to cancel the mailing request.
  28852. )INIT
  28853.  .HELP = TNNM
  28854.  IF (&NNMAILOT = &Z) &HEADING = 'New mail message'
  28855.  ELSE                &HEADING = 'Reply to message from &NNMAILOT'
  28856.  IF (&NNMAILTO = &Z) .CURSOR = NNMAILTO
  28857.  ELSE                .CURSOR = NNMAILSJ
  28858.  &ZWINTTL = 'Send a mail message or reply'
  28859.  &END = PFK(END)
  28860.  &ZCMD = &Z
  28861.  IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
  28862.  /* IF (&NNMAILSF = &Z) &NNMAILSF = &NNPOSTSF */
  28863. )PROC
  28864.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28865.  VER(&NNMAILTO,NB)
  28866.  VER(&NNMAILSJ,NB)
  28867.  VER(&NNMAILSF,DSNAME)
  28868.  VER(&NNEDPROF,NAME)
  28869.  IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
  28870.  VPUT (NNMAILRT NNMAILFR NNMAILSF NNEDPROF) PROFILE
  28871. )END
  28872. ./   ADD NAME=NNMQPOST,SSI=01040000
  28873. )ATTR
  28874. /*                                                                   /*
  28875. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28876. /*                                                                   /*
  28877. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28878. /* including the implied warranties of merchantability and fitness,  /*
  28879. /* are expressly denied.                                             /*
  28880. /*                                                                   /*
  28881. /* Provided this copyright notice is included, this software may     /*
  28882. /* be freely distributed and not offered for sale.                   /*
  28883. /*                                                                   /*
  28884. /* Changes or modifications may be made and used only by the maker   /*
  28885. /* of same, and not further distributed.  Such modifications should  /*
  28886. /* be mailed to the author for consideration for addition to the     /*
  28887. /* software and incorporation in subsequent releases.                /*
  28888. /*                                                                   /*
  28889.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  28890. /*                                                                   /*
  28891. /* There seems to be some kind of bug in ISPF 3.3.  Substitution of  /*
  28892. /* variables is not done before the first input field, so I could    /*
  28893. /* not put the panel heading where I wanted it. ???                  /*
  28894. /*                                                                   /*
  28895. )BODY EXPAND(``)
  28896.  -`-`- Post to news server -`-`-
  28897. %Command ===>^ZCMD
  28898.  
  28899. %Note:+The fate of a posted news article is determined by the%news server+
  28900.       %(&NNSERVER).
  28901.  
  28902. +Posting:  &HEADING
  28903.  
  28904. %Required Header Fields+
  28905.  
  28906. +Newsgroups  ===>^NNPOSTNG
  28907. +Subject     ===>^NNPOSTSJ
  28908.  
  28909. %Optional Header Fields+
  28910.  
  28911. +Reply To     ==>^NNPOSTRT
  28912. +Followup To  ==>^NNPOSTFO
  28913.  
  28914. +Your human name ==>^NNPOSTFR
  28915. +Signature file  ==>_NNPOSTSF
  28916. +Edit profile    ==>_NNEDPROF+
  28917.  
  28918. +Press%ENTER+to proceed to the editor to compose the article.
  28919. +Press%&END (END)+to cancel the posting request.
  28920. )INIT
  28921.  .HELP = TNNM
  28922.  IF (&NNPOSTHA = &Z)
  28923.   &HEADING = 'New Article'
  28924.  ELSE
  28925.   &HEADING = 'Followup to Article &NNPOSTHA in group &NNPOSTHG'
  28926.  IF (&NNPOSTNG = &Z) .CURSOR = NNPOSTNG
  28927.  ELSE                .CURSOR = NNPOSTSJ
  28928.  &END = PFK(END)
  28929.  &ZCMD = &Z
  28930.  IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
  28931.  /* IF (&NNPOSTSF = &Z) &NNPOSTSF = &NNMAILSF */
  28932. )PROC
  28933.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28934.  VER(&NNPOSTNG,NB)
  28935.  VER(&NNPOSTSJ,NB)
  28936.  VER(&NNPOSTSF,DSNAME)
  28937.  VER(&NNEDPROF,NAME)
  28938.  IF (&NNEDPROF = &Z) &NNEDPROF = TEXT
  28939.  VPUT (NNPOSTRT NNPOSTFR NNPOSTSF NNEDPROF) PROFILE
  28940. )END
  28941. ./   ADD NAME=NNMRCERR,SSI=01050000
  28942. )ATTR
  28943. /*                                                                   /*
  28944. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28945. /*                                                                   /*
  28946. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28947. /* including the implied warranties of merchantability and fitness,  /*
  28948. /* are expressly denied.                                             /*
  28949. /*                                                                   /*
  28950. /* Provided this copyright notice is included, this software may     /*
  28951. /* be freely distributed and not offered for sale.                   /*
  28952. /*                                                                   /*
  28953. /* Changes or modifications may be made and used only by the maker   /*
  28954. /* of same, and not further distributed.  Such modifications should  /*
  28955. /* be mailed to the author for consideration for addition to the     /*
  28956. /* software and incorporation in subsequent releases.                /*
  28957. /*                                                                   /*
  28958.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  28959.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  28960.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  28961.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  28962.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  28963.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  28964.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  28965. )BODY EXPAND(``)
  28966. %-`-`-  MVS Network News Viewer -`-`-
  28967. %COMMAND ===>_ZCMD
  28968. +
  28969. %  ` `  *** ERROR ***  ` ` +
  28970. +
  28971. % ` ` Unable to access the NEWSRC file, which is required. ` ` +
  28972. +
  28973. + ` ` This file must be allocated to DDname%NNNEWSRC. ` ` +
  28974. +
  28975. + ` ` The News Viewer cannot continue. ` ` +
  28976. +
  28977. +
  28978. + ` ` Press!ENTER+or!END+key to leave this panel. ` ` +
  28979. )INIT
  28980.  .HELP = TNNM
  28981. )PROC
  28982.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  28983. )END
  28984. ./   ADD NAME=NNMRFCH,SSI=01030029
  28985. )ATTR
  28986. /*                                                                   /*
  28987. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  28988. /*                                                                   /*
  28989. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  28990. /* including the implied warranties of merchantability and fitness,  /*
  28991. /* are expressly denied.                                             /*
  28992. /*                                                                   /*
  28993. /* Provided this copyright notice is included, this software may     /*
  28994. /* be freely distributed and not offered for sale.                   /*
  28995. /*                                                                   /*
  28996. /* Changes or modifications may be made and used only by the maker   /*
  28997. /* of same, and not further distributed.  Such modifications should  /*
  28998. /* be mailed to the author for consideration for addition to the     /*
  28999. /* software and incorporation in subsequent releases.                /*
  29000. /*                                                                   /*
  29001.  ! TYPE(TEXT) INTENS(LOW)
  29002.  ? TYPE(TEXT) INTENS(LOW)
  29003.  { TYPE(TEXT) INTENS(LOW)
  29004.  } TYPE(TEXT) INTENS(LOW)
  29005. )BODY EXPAND(``)
  29006. %-`-`- NNMVS - RFC822 Header Viewing Options -`-`-
  29007. %Command ===>_ZCMD
  29008. +
  29009. +The current RFC822 header viewing option is highlighted.
  29010. +Move cursor to choice (or type%S+next to choice) and press%ENTER+to change:
  29011. +
  29012. _A!Show all RFC822 headers
  29013. _B?Show all RFC822 headers except those in Exclude List
  29014. _C{Show the RFC822 headers in Include List only
  29015. _D}Suppress RFC822 headers entirely
  29016. +
  29017. +Lists are header names separated by blanks.  Do%not+put%:+in header names.
  29018. +
  29019. %Include List ==>_NNRFCINC
  29020.  
  29021.  
  29022. %Exclude List ==>_NNRFCEXC
  29023.  
  29024.  
  29025. +Press%ENTER+to change options.  Press%&END+(or type%END+command) when done.
  29026. )INIT
  29027.  .HELP = TNNMOPT
  29028.  .CURSOR = ZCMD
  29029.  &END = PFK(END)
  29030.  &ZCMD = &Z
  29031.  &A = &Z 
  29032.  &B = &Z 
  29033.  &C = &Z 
  29034.  &D = &Z 
  29035.  VGET (NNRFCOPT NNRFCINC NNRFCEXC) PROFILE
  29036.  IF (&NNRFCOPT = &Z) &NNRFCOPT = A
  29037.  IF (&NNRFCOPT = A) .ATTRCHAR(!) = 'INTENS(HIGH)'
  29038.  IF (&NNRFCOPT = B) .ATTRCHAR(?) = 'INTENS(HIGH)'
  29039.  IF (&NNRFCOPT = C) .ATTRCHAR({) = 'INTENS(HIGH)'
  29040.  IF (&NNRFCOPT = D) .ATTRCHAR(}) = 'INTENS(HIGH)'
  29041.  IF (&NNRFCOPT = B) .ATTR(NNRFCEXC) = 'INTENS(HIGH)'
  29042.  ELSE               .ATTR(NNRFCEXC) = 'INTENS(LOW)'
  29043.  IF (&NNRFCOPT = C) .ATTR(NNRFCINC) = 'INTENS(HIGH)'
  29044.  ELSE               .ATTR(NNRFCINC) = 'INTENS(LOW)'
  29045. )PROC
  29046.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  29047.  IF (.RESP = ENTER)
  29048.   &TEMP = '&A/&B/&C/&D'
  29049.   IF (&TEMP = '///')
  29050.    &NNCHOICE = TRANS(.CURSOR A A B B C C D D * ' ')
  29051.   ELSE
  29052.    &NNCHOICE = TRANS(&TEMP  'S///' A
  29053.                             '/S//' B
  29054.                             '//S/' C
  29055.                             '///S' D
  29056.                                * ?  )
  29057.   IF (&NNCHOICE = '?')
  29058.    &ZERRSM   = 'Invalid choice'
  29059.    &ZERRLM   = 'Make exactly one selection with the cursor or type only one S.'
  29060.    &ZERRALRM = YES
  29061.    &ZERRHM   = '*'
  29062.    .MSG = ISRZ002
  29063.   ELSE
  29064.    IF (&NNCHOICE ^= &Z)
  29065.     &NNRFCOPT = &NNCHOICE
  29066.   VPUT (NNRFCOPT NNRFCINC NNRFCEXC) PROFILE
  29067. )END
  29068. ./   ADD NAME=NNMVIEW,SSI=01030025
  29069. )ATTR DEFAULT(%+_)
  29070. /*                                                                   */
  29071. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     */
  29072. /*                                                                   */
  29073. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           */
  29074. /*                                                                   */
  29075. /* This software is provided on an "AS IS" basis.  All warranties,   */
  29076. /* including the implied warranties of merchantability and fitness,  */
  29077. /* are expressly denied.                                             */
  29078. /*                                                                   */
  29079. /* Provided this copyright notice is included, this software may     */
  29080. /* be freely distributed and not offered for sale.                   */
  29081. /*                                                                   */
  29082. /* Changes or modifications may be made and used only by the maker   */
  29083. /* of same, and not further distributed.  Such modifications should  */
  29084. /* be mailed to the author for consideration for addition to the     */
  29085. /* software and incorporation in subsequent releases.                */
  29086. /*                                                                   */
  29087.  ^  TYPE(INPUT)  INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29088.  #  TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(RIGHT)
  29089.  \  TYPE(OUTPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29090.  |  AREA(DYNAMIC) EXTEND(ON) SCROLL(ON) USERMOD(05)
  29091.  01 TYPE(DATAOUT) INTENS(LOW)
  29092.  02 TYPE(DATAOUT) INTENS(HIGH)
  29093.  03 TYPE(DATAIN)  INTENS(LOW)
  29094.  04 TYPE(DATAIN)  INTENS(HIGH)
  29095. )BODY
  29096. \NNBTITLE
  29097. %COMMAND ===>^ZCMD                                            %SCROLL ===>_Z   +
  29098. |NNBDYNA                                                                       |
  29099. )INIT
  29100.  .ZVARS = NNMARTSC
  29101.  IF (&NNMARTSC = &Z) &NNMARTSC = CSR
  29102.  &TNNMTHR = 'NNMVIEW'
  29103.  .HELP = TNNMB1
  29104.  .CURSOR = &NNBCUR
  29105.  .CSRPOS = &NNBPOS
  29106. )PROC
  29107.  &NNBCUR = .CURSOR
  29108.  &NNBPOS = .CSRPOS
  29109.  &NNBLVL = LVLINE(NNBDYNA)
  29110.  VPUT (NNMARTSC) PROFILE
  29111. )END
  29112. ./   ADD NAME=NNM0,SSI=01070048
  29113. )ATTR
  29114. /*                                                                   /*
  29115. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29116. /*                                                                   /*
  29117. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29118. /* including the implied warranties of merchantability and fitness,  /*
  29119. /* are expressly denied.                                             /*
  29120. /*                                                                   /*
  29121. /* Provided this copyright notice is included, this software may     /*
  29122. /* be freely distributed and not offered for sale.                   /*
  29123. /*                                                                   /*
  29124. /* Changes or modifications may be made and used only by the maker   /*
  29125. /* of same, and not further distributed.  Such modifications should  /*
  29126. /* be mailed to the author for consideration for addition to the     /*
  29127. /* software and incorporation in subsequent releases.                /*
  29128. /*                                                                   /*
  29129.  _ TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29130.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29131.  @ TYPE(TEXT) INTENS(HIGH) COLOR(PINK)
  29132.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29133.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29134.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29135.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29136.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29137. )BODY EXPAND(``)
  29138. %-`-`-  MVS Network News Client: NNTP Native Protocol Mode  -`-`-
  29139. %COMMAND ===>_ZCMD
  29140. +
  29141. %NNTP command ===>_NNCMD
  29142. +
  29143. +
  29144. +Press!END+key to leave this menu.
  29145. )INIT
  29146.  .HELP = TNNM
  29147.  .CURSOR = NNCMD
  29148.  &ZCMD = &Z
  29149. )PROC
  29150.  IF (&ZCMD ^= &Z) .MSG=ISPZ001
  29151. )END
  29152. ./   ADD NAME=ONMBROBF,SSI=01000046
  29153. )ATTR
  29154. /*                                                                   */
  29155. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     */
  29156. /*                                                                   */
  29157. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           */
  29158. /*                                                                   */
  29159. /* This software is provided on an "AS IS" basis.  All warranties,   */
  29160. /* including the implied warranties of merchantability and fitness,  */
  29161. /* are expressly denied.                                             */
  29162. /*                                                                   */
  29163. /* Provided this copyright notice is included, this software may     */
  29164. /* be freely distributed and not offered for sale.                   */
  29165. /*                                                                   */
  29166. /* Changes or modifications may be made and used only by the maker   */
  29167. /* of same, and not further distributed.  Such modifications should  */
  29168. /* be mailed to the author for consideration for addition to the     */
  29169. /* software and incorporation in subsequent releases.                */
  29170. /*                                                                   */
  29171.    _ TYPE(INPUT) CAPS(OFF) INTENS(HIGH) FORMAT(&MIXED)
  29172.    + TYPE(TEXT) INTENS(LOW)
  29173. )BODY  WIDTH(&ZWIDTH) EXPAND(//)
  29174. %BROWSE ----------------------------------/-/----------------------------------+
  29175. %COMMAND ===>_ZCMD                        / /                 %SCROLL ===>_Z   +
  29176. )INIT
  29177.   &TNNMTHR = 'NNMBROBF'
  29178.   .HELP = TNNMB1
  29179.   .ZVARS = 'ZSCBR'
  29180.   &MIXED = MIX             /* SET FORMAT MIX            */
  29181.   IF (&ZPDMIX = N)         /* IF EBCDIC MODE REQUESTED  */
  29182.     &MIXED = EBCDIC        /*  SET FORMAT EBCDIC        */
  29183. )END
  29184. /* 5665-402 (C) COPYRIGHT IBM CORP 1980, 1989 */
  29185. ./   ADD NAME=ONMPPRDS,SSI=01090042
  29186. )ATTR
  29187. /*                                                                   /*
  29188. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     /*
  29189. /*                                                                   /*
  29190. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29191. /* including the implied warranties of merchantability and fitness,  /*
  29192. /* are expressly denied.                                             /*
  29193. /*                                                                   /*
  29194. /* Provided this copyright notice is included, this software may     /*
  29195. /* be freely distributed and not offered for sale.                   /*
  29196. /*                                                                   /*
  29197. /* Changes or modifications may be made and used only by the maker   /*
  29198. /* of same, and not further distributed.  Such modifications should  /*
  29199. /* be mailed to the author for consideration for addition to the     /*
  29200. /* software and incorporation in subsequent releases.                /*
  29201. /*                                                                   /*
  29202.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29203. )BODY WINDOW(77,11)
  29204. +
  29205. %Command ===>^ZCMD
  29206. +
  29207. +&NUMBER       %&SUBJECT
  29208. +
  29209. +SYSOUT class ===>_Z+   Number of copies ===>_Z  +
  29210.  
  29211. +(Note: Print data will be released to SYSOUT immediately.)
  29212.  
  29213.  
  29214. +Press%&END (END)+to cancel the print request.
  29215. )INIT
  29216.  .HELP = TNNM
  29217.  .ZVARS = '(NNEXSCL NNEXSCO)'
  29218.  .CURSOR = NNEXSCL
  29219.  IF (&NNTNUM ^= &Z)
  29220.   &ZWINTTL = 'Print from &NNGROUP'
  29221.   &NUMBER  = 'Article &NNTNUM: '
  29222.   &SUBJECT = '&NNTSUBJ'
  29223.  ELSE
  29224.   &ZWINTTL = 'Print text'
  29225.   &NUMBER  = ' '
  29226.   &SUBJECT = ' '
  29227.  &END = PFK(END)
  29228.  &ZCMD = &Z
  29229.  VGET (NNEXSCL) PROFILE
  29230.  &NNEXSCO = 1
  29231. )PROC
  29232.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  29233.  VER(&NNEXSCL,NB,NAME)
  29234.  IF (&NNEXSCO = &Z) &NNEXSCO = 1
  29235.  VER(&NNEXSCO,NUM)
  29236.  VER(&NNEXSCO,RANGE,1,255)
  29237.  VPUT (NNEXSCL) PROFILE
  29238. )END
  29239. ./   ADD NAME=ONMPPRMG,SSI=01080031
  29240. )ATTR
  29241. /*                                                                   /*
  29242. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     /*
  29243. /*                                                                   /*
  29244. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29245. /* including the implied warranties of merchantability and fitness,  /*
  29246. /* are expressly denied.                                             /*
  29247. /*                                                                   /*
  29248. /* Provided this copyright notice is included, this software may     /*
  29249. /* be freely distributed and not offered for sale.                   /*
  29250. /*                                                                   /*
  29251. /* Changes or modifications may be made and used only by the maker   /*
  29252. /* of same, and not further distributed.  Such modifications should  /*
  29253. /* be mailed to the author for consideration for addition to the     /*
  29254. /* software and incorporation in subsequent releases.                /*
  29255. /*                                                                   /*
  29256.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29257. )BODY WINDOW(77,9)
  29258. +
  29259. %Command ===>^ZCMD
  29260. +
  29261. +SYSOUT class ===>_Z+   Number of copies ===>_Z  +
  29262.  
  29263. +(Note: Print data will be released to SYSOUT immediately.)
  29264.  
  29265.  
  29266. +Press%&END (END)+to cancel the print request.
  29267. )INIT
  29268.  .HELP = TNNM
  29269.  .ZVARS = '(NNEXSCL NNEXSCO)'
  29270.  .CURSOR = NNEXSCL
  29271.  &ZWINTTL = 'Print newsgroup listing'
  29272.  &END = PFK(END)
  29273.  &ZCMD = &Z
  29274.  VGET (NNEXSCL) PROFILE
  29275.  &NNEXSCO = 1
  29276. )PROC
  29277.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  29278.  VER(&NNEXSCL,NB,NAME)
  29279.  IF (&NNEXSCO = &Z) &NNEXSCO = 1
  29280.  VER(&NNEXSCO,NUM)
  29281.  VER(&NNEXSCO,RANGE,1,255)
  29282.  VPUT (NNEXSCL) PROFILE
  29283. )END
  29284. ./   ADD NAME=ONMPPRNS,SSI=01070034
  29285. )ATTR
  29286. /*                                                                   /*
  29287. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     /*
  29288. /*                                                                   /*
  29289. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29290. /* including the implied warranties of merchantability and fitness,  /*
  29291. /* are expressly denied.                                             /*
  29292. /*                                                                   /*
  29293. /* Provided this copyright notice is included, this software may     /*
  29294. /* be freely distributed and not offered for sale.                   /*
  29295. /*                                                                   /*
  29296. /* Changes or modifications may be made and used only by the maker   /*
  29297. /* of same, and not further distributed.  Such modifications should  /*
  29298. /* be mailed to the author for consideration for addition to the     /*
  29299. /* software and incorporation in subsequent releases.                /*
  29300. /*                                                                   /*
  29301.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29302. )BODY EXPAND(``) WINDOW(77,16)
  29303. +
  29304. %Command ===>^ZCMD
  29305. +
  29306. +SYSOUT class ===>_Z+   Number of copies ===>_Z  +
  29307.  
  29308. +(Note: Print data will be released to SYSOUT immediately.)
  29309. +
  29310. +Page eject between articles?     %===>_Z  +
  29311. +Blank line after separator?      %===>_Z  +
  29312. +Separator line before each article (leave blank for none):
  29313. +>^Z                                                                       +<
  29314.  
  29315. +From article number%===>_NNEXAN1      + (blank for first article in table)
  29316. +To   article number%===>_NNEXAN2      + (blank for last article in table)
  29317.  
  29318. +Press%&END (END)+to cancel the print request.
  29319. )INIT
  29320.  .HELP = TNNM
  29321.  .ZVARS = '(NNEXSCL NNEXSCO NNEXSPA NNEXBLK NNEXSEP)'
  29322.  .CURSOR = ZCMD
  29323.  &ZWINTTL = 'Print text of articles in &NNGROUP'
  29324.  &END = PFK(END)
  29325.  &ZCMD = &Z
  29326.  VGET (NNEXSCL NNEXSPA NNEXBLK NNEXSEP) PROFILE
  29327.  &NNEXSPA = TRANS(&NNEXSPA Y,YES N,NO ' ',NO)
  29328.  &NNEXBLK = TRANS(&NNEXBLK Y,YES N,NO ' ',NO)
  29329.  &NNEXSCO = 1
  29330.  &NNEXAN1 = &Z
  29331.  &NNEXAN2 = &Z
  29332. )PROC
  29333.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  29334.  VER(&NNEXSCL,NB,NAME)
  29335.  &NNEXSPA = TRUNC(&NNEXSPA,1)
  29336.  &NNEXBLK = TRUNC(&NNEXBLK,1)
  29337.  VER(&NNEXSPA,NB,LIST,Y,N)
  29338.  VER(&NNEXBLK,NB,LIST,Y,N)
  29339.  IF (&NNEXSCO = &Z) &NNEXSCO = 1
  29340.  VER(&NNEXSCO,NUM)
  29341.  VER(&NNEXSCO,RANGE,1,255)
  29342.  VER(&NNEXAN1,NUM)
  29343.  VER(&NNEXAN2,NUM)
  29344.  VPUT (NNEXSCL NNEXSPA NNEXBLK NNEXSEP) PROFILE
  29345. )END
  29346. ./   ADD NAME=ONMPPRN1,SSI=01070041
  29347. )ATTR
  29348. /*                                                                   /*
  29349. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     /*
  29350. /*                                                                   /*
  29351. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29352. /* including the implied warranties of merchantability and fitness,  /*
  29353. /* are expressly denied.                                             /*
  29354. /*                                                                   /*
  29355. /* Provided this copyright notice is included, this software may     /*
  29356. /* be freely distributed and not offered for sale.                   /*
  29357. /*                                                                   /*
  29358. /* Changes or modifications may be made and used only by the maker   /*
  29359. /* of same, and not further distributed.  Such modifications should  /*
  29360. /* be mailed to the author for consideration for addition to the     /*
  29361. /* software and incorporation in subsequent releases.                /*
  29362. /*                                                                   /*
  29363.        ^   TYPE(INPUT) INTENS(HIGH) CAPS(OFF) JUST(LEFT)
  29364. )BODY WINDOW(77,9)
  29365. +
  29366. %Command ===>^ZCMD
  29367. +
  29368. +SYSOUT class ===>_Z+   Number of copies ===>_Z  +
  29369.  
  29370. +(Note: Print data will be released to SYSOUT immediately.)
  29371.  
  29372.  
  29373. +Press%&END (END)+to cancel the print request.
  29374. )INIT
  29375.  .HELP = TNNM
  29376.  .ZVARS = '(NNEXSCL NNEXSCO)'
  29377.  .CURSOR = NNEXSCL
  29378.  &ZWINTTL = 'Print news article listing'
  29379.  &END = PFK(END)
  29380.  &ZCMD = &Z
  29381.  VGET (NNEXSCL) PROFILE
  29382.  &NNEXSCO = 1
  29383. )PROC
  29384.  IF (&ZCMD ^= &Z) .MSG = ISPZ001
  29385.  VER(&NNEXSCL,NB,NAME)
  29386.  IF (&NNEXSCO = &Z) &NNEXSCO = 1
  29387.  VER(&NNEXSCO,NUM)
  29388.  VER(&NNEXSCO,RANGE,1,255)
  29389.  VPUT (NNEXSCL) PROFILE
  29390. )END
  29391. ./   ADD NAME=SASPANEL,SSI=01000042
  29392.  
  29393. (from Dale Ingold SNODDI@mvs.sas.com)
  29394.  
  29395. Here's the complete print panel, NNMQPRT.  I've changed every non-
  29396. printable character to /xNN. (Would've used \, but that's my command
  29397. separator character.)
  29398.  
  29399. )PANEL KEYLIST(ISPSNAB,ISP)
  29400. )ATTR DEFAULT(/x01/x02/x03)
  29401.  /x04 TYPE(TEXT) INTENS(LOW) SKIP(OFF) FORMAT(MIX) COLOR(BLUE)
  29402.  /x05 TYPE(TEXT) INTENS(LOW) SKIP(OFF) FORMAT(MIX) COLOR(GREEN)
  29403.  /x0A TYPE(OUTPUT) INTENS(LOW) FORMAT(MIX) CAPS(OFF) COLOR(WHITE)
  29404.  /x09 TYPE(INPUT) INTENS(LOW) CAPS(OFF) JUST(LEFT) FORMAT(MIX)
  29405.     PADC('_') COLOR(TURQ)
  29406.  /x19 TYPE(INPUT) INTENS(LOW) CAPS(ON) JUST(LEFT) FORMAT(MIX)
  29407.     PADC('_') COLOR(TURQ)
  29408.  /x17 TYPE(TEXT) INTENS(LOW) SKIP(OFF) FORMAT(MIX) COLOR(TURQ)
  29409. )BODY WINDOW(60,22) CMD(ZCMD)
  29410. /x04                 Set Print Options
  29411. /x05Command ===>/x09Z
  29412. /x04
  29413. /x05Article to be printed:
  29414. /x04
  29415. /x05Article nbr:/x0AZ /x17
  29416. /x05From . . . :/x0AZ                                 /x17
  29417. /x05Date . . . :/x0AZ                                 /x17
  29418. /x05Subject . :/x0AZ                                  /x17
  29419. /x05Message ID :/x0AZ                                 /x17
  29420. /x04
  29421. /x05Enter/verify the parameters below:                     /x05
  29422. /x05                                                       /x05
  29423. /x05Destination /x09Z /x17
  29424. /x05Copies . . ./x09Z /x17/x05(Default is 1 copy) /x17
  29425. /x05Heading . ./x19Z /x17/x05(Yes to print heading) /x17
  29426. /x05Hold . . . ./x19Z /x17/x05(Yes to hold SYSOUT) /x17
  29427. /x05Form . . . ./x09Z /x17
  29428. /x05UCS . . . ./x09Z /x17
  29429. /x04
  29430. /x05Press ENTER to print or CANCEL to return.
  29431. )INIT
  29432. .ZVARS = '( ZCMD NNMPRTNM NNMPRTFM NNMPRTDT NNMPRTSJ NNMPRTID +
  29433.             DEST CP HEAD HOLD FORM UCS )'
  29434. .HELP = TNNMQPRT
  29435. &ZCMD = ' '
  29436. &HEAD=TRANS (&HEAD
  29437. 'Y','YES' 'Y','YO' 'N','NO' 'N','NES')
  29438. &HOLD=TRANS (&HOLD
  29439. 'Y','YES' 'Y','YO' 'N','NO' 'N','NES')
  29440. )PROC
  29441. VER (&CP NUM)
  29442. &HEAD=TRANS (&HEAD
  29443. 'YES','Y' 'YO','Y' 'NO','N' 'NES','N')
  29444. VER (&HEAD
  29445. LIST,Y,N )
  29446. &HOLD=TRANS (&HOLD
  29447. 'YES','Y' 'YO','Y' 'NO','N' 'NES','N')
  29448. VER (&HOLD
  29449. LIST,Y,N )
  29450. )END
  29451. ./   ADD NAME=TNNM
  29452. )ATTR
  29453. /*                                                                   /*
  29454. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29455. /*                                                                   /*
  29456. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29457. /*                                                                   /*
  29458. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29459. /* including the implied warranties of merchantability and fitness,  /*
  29460. /* are expressly denied.                                             /*
  29461. /*                                                                   /*
  29462. /* Provided this copyright notice is included, this software may     /*
  29463. /* be freely distributed and not offered for sale.                   /*
  29464. /*                                                                   /*
  29465. /* Changes or modifications may be made and used only by the maker   /*
  29466. /* of same, and not further distributed.  Such modifications should  /*
  29467. /* be mailed to the author for consideration for addition to the     /*
  29468. /* software and incorporation in subsequent releases.                /*
  29469. /*                                                                   /*
  29470.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29471.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29472.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29473.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29474.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29475.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29476. )BODY EXPAND(``)
  29477. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29478. %SELECTION ===>_ZCMD                                                           +
  29479. %
  29480. +NNMVS is an NNTP (network news transfer protocol)%news client+that runs on the
  29481.  IBM mainframe using ISPF services.  It retrieves news articles from an NNTP
  29482. %news server+executing on a host machine elsewhere on your network.  You must
  29483.  tell NNMVS where this news server is; it does not know otherwise.
  29484.  
  29485. +NNMVS remembers which articles you have read in a%"newsrc"+file, whose name
  29486.  defaults to%&ZPREFIX..NEWSRC+.  If you are a new user, you use the%L+or%blank+
  29487. +option to build your NEWSRC file with a list retrieved from the server.  To
  29488.  limit the list to your favorite newsgroups, you can register (subscribe to)
  29489.  the ones you want while viewing the newsgroup list.  Once you have used NNMVS
  29490.  and built a NEWSRC file, you may wish to use a different entry option to reduce
  29491.  startup time.  You can avoid retrieving the whole list by using the%R+option to
  29492.  view only%registered+(subscribed) newsgroups, or the%A+option to view%all+
  29493.  newsgroups listed in your NEWSRC file.  You can use the%N+option to get a list
  29494.  of newsgroups added since the last time you retrieved the newsgroup list (i.e.
  29495.  used%L+or%N+).  The%G+option always goes directly to a specific newsgroup.
  29496.  
  29497. +Press%ENTER+to proceed with the tutorial, or enter a selection code:
  29498.     %1+- Information on news servers
  29499.     %2+- Information on NNTP, as described by RFC 977
  29500. )INIT
  29501. )PROC
  29502.  &ZSEL = TRANS(&ZCMD,1,TNNMSERV,2,TNNMNNTP,*,?)
  29503.  &ZCONT = TNNM001
  29504. )END
  29505. ./   ADD NAME=TNNMB1,SSI=01020021
  29506. )ATTR
  29507. /*                                                                   /*
  29508. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29509. /*                                                                   /*
  29510. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29511. /*                                                                   /*
  29512. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29513. /* including the implied warranties of merchantability and fitness,  /*
  29514. /* are expressly denied.                                             /*
  29515. /*                                                                   /*
  29516. /* Provided this copyright notice is included, this software may     /*
  29517. /* be freely distributed and not offered for sale.                   /*
  29518. /*                                                                   /*
  29519. /* Changes or modifications may be made and used only by the maker   /*
  29520. /* of same, and not further distributed.  Such modifications should  /*
  29521. /* be mailed to the author for consideration for addition to the     /*
  29522. /* software and incorporation in subsequent releases.                /*
  29523. /*                                                                   /*
  29524.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29525.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29526.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29527.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29528.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29529.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29530. )BODY EXPAND(``)
  29531. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29532. %SELECTION ===>_ZCMD                                                           +
  29533. +When you select an article for viewing, you are placed in browse mode.
  29534. +You can use most NNMVS and ISPF BROWSE commands, plus the following commands:
  29535. %NEXT+           - proceed directly to the next article in the newsgroup
  29536. %NEXTSubj+ or%NS+- proceed directly to the next article on the same subject
  29537. %NEXTT+    or%NT+- proceed directly to the next article in the current table
  29538. %NEXTU+    or%NU+- proceed directly to the next unread article in the newsgroup
  29539. %PREV+           - proceed directly to the previous article in the newsgroup
  29540. %PREVSubj+ or%PS+- proceed directly to the previous article on the same subject
  29541. %PREVT+    or%PT+- proceed directly to the previous article in the current table
  29542. %PREVU+    or%PU+- proceed directly to the previous unread article in the group
  29543. %FIRSTSubj+or%FS+- proceed directly to first unread article on the same subject
  29544. %LASTSubj +or%LS+- proceed directly to last unread article on the same subject
  29545. %NEWSUBJ+        - proceed directly to first unread article on different subject
  29546. %SUBJECT+or%SUBJ+- display or change the current subject for subject searches
  29547. %UNREAD+         - stop reading this article and mark it unread
  29548. %EXTRACT+or%EXT+ - copy the article into a data set
  29549. %PRT+or%PRNT+    - print the article to SYSOUT
  29550. %ROT13+          - display "ROT13"-encoded text (toggle, do it again to reverse)
  29551. %FOLLOWUP+       - post a follow-up news article, news server permitting
  29552. %REPLY+          - send private mail to the originator of the news article
  29553. %HEADERs+        - customize article header line display (same as OPTIONS 1)
  29554.                           %(continued on next page)+
  29555. )INIT
  29556.  IF (&TNNMTHR = NNMBROBF) &ZUP = ISR10000
  29557.  ELSE                     &ZUP = TNNM001
  29558.  &ZCONT = TNNMB2
  29559. )PROC
  29560. )END
  29561. ./   ADD NAME=TNNMB2
  29562. )ATTR
  29563. /*                                                                   /*
  29564. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29565. /*                                                                   /*
  29566. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29567. /*                                                                   /*
  29568. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29569. /* including the implied warranties of merchantability and fitness,  /*
  29570. /* are expressly denied.                                             /*
  29571. /*                                                                   /*
  29572. /* Provided this copyright notice is included, this software may     /*
  29573. /* be freely distributed and not offered for sale.                   /*
  29574. /*                                                                   /*
  29575. /* Changes or modifications may be made and used only by the maker   /*
  29576. /* of same, and not further distributed.  Such modifications should  /*
  29577. /* be mailed to the author for consideration for addition to the     /*
  29578. /* software and incorporation in subsequent releases.                /*
  29579. /*                                                                   /*
  29580.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29581.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29582.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29583.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29584.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29585.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29586. )BODY EXPAND(``)
  29587. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29588. %SELECTION ===>_ZCMD                                                           +
  29589. %
  29590. +All the commands of ISPF BROWSE are supported under NNMVS browse, except for:
  29591.  
  29592.  %HEX+
  29593.  %BROWSE+
  29594.  %SUBMIT+
  29595.  %LOCATE .label+
  29596.  %.<string>+(to assign a label)
  29597.  %FIND P'generic-string'+
  29598.  %DISPLAY CC/NOCC+
  29599.  
  29600. +For NEXTSUBJ, PREVSUBJ, FIRSTSUBJ and LASTSUBJ, the current subject is that
  29601.  of the article being displayed.   Alphabetic case is ignored, and subjects
  29602.  with RE: and WAS: wrappers are taken into account.
  29603.  
  29604. +Note that NNTP protocol displays also use browse mode.  When you are browsing
  29605.  such output, commands relevant to article selection or sending are not
  29606.  available.  This means that EXTRACT and PRT are the only commands other
  29607.  than browse and general NNMVS commands that you can use at such a time.
  29608. )INIT
  29609. )PROC
  29610. )END
  29611. ./   ADD NAME=TNNMC,SSI=01000049
  29612. )ATTR
  29613. /*                                                                   /*
  29614. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1993     /*
  29615. /*                                                                   /*
  29616. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29617. /* including the implied warranties of merchantability and fitness,  /*
  29618. /* are expressly denied.                                             /*
  29619. /*                                                                   /*
  29620. /* Provided this copyright notice is included, this software may     /*
  29621. /* be freely distributed and not offered for sale.                   /*
  29622. /*                                                                   /*
  29623. /* Changes or modifications may be made and used only by the maker   /*
  29624. /* of same, and not further distributed.  Such modifications should  /*
  29625. /* be mailed to the author for consideration for addition to the     /*
  29626. /* software and incorporation in subsequent releases.                /*
  29627. /*                                                                   /*
  29628.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29629.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29630.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29631.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29632.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29633.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29634. )BODY EXPAND(``)
  29635. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29636. %SELECTION ===>_ZCMD                                                           +
  29637.  
  29638. +The following commands are available from any of the display modes:
  29639.  
  29640.  %OPTIONS+or%OPT+- set user options (e.g. for display of message headers)
  29641.  %SAVE          +- checkpoint%newsrc+(otherwise, will not be updated until exit)
  29642.  %POST          +- compose a news article for sending, news server permitting
  29643.  %MAIL          +- compose a mail message for sending to an individual user
  29644.  %NNTP          +- enter native NNTP protocol mode (for debugging only)
  29645.  %DISCONNECT    +- force disconnection from news server (reconnect automatic)
  29646.  %QUIT          +- leave NNMVS, saving changes in NEWSRC file
  29647.  %CRASHNNMVS    +- terminate NNMVS immediately, saving nothing
  29648.  %DEBUG         +- enable NNMVS debug mode (ddname NNDEBUG must be allocated)
  29649.  %NODEBUG       +- deactivate NNMVS debug mode
  29650.  %TEST          +- enter C/370 test mode (INSPECT)
  29651.  
  29652. +The following topics will be displayed next, or may be selected by number:
  29653.  
  29654. %   1 + - The Newsgroup Display (Available Selection Codes and Commands)
  29655. %   2 + - The Article Display   (Available Selection Codes and Commands)
  29656. %   3 + - The Text Display      (Available Commands)
  29657. %   4 + - Specifying User Options
  29658. )INIT
  29659. )PROC
  29660.  &ZSEL = TRANS(&ZCMD 1,TNNMG 2,TNNMT 3,TNNMB1 4,TNNMOPT *,?)
  29661.  &ZUP = TNNM
  29662. )END
  29663. ./   ADD NAME=TNNMG,SSI=01020043
  29664. )ATTR
  29665. /*                                                                   /*
  29666. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29667. /*                                                                   /*
  29668. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29669. /* including the implied warranties of merchantability and fitness,  /*
  29670. /* are expressly denied.                                             /*
  29671. /*                                                                   /*
  29672. /* Provided this copyright notice is included, this software may     /*
  29673. /* be freely distributed and not offered for sale.                   /*
  29674. /*                                                                   /*
  29675. /* Changes or modifications may be made and used only by the maker   /*
  29676. /* of same, and not further distributed.  Such modifications should  /*
  29677. /* be mailed to the author for consideration for addition to the     /*
  29678. /* software and incorporation in subsequent releases.                /*
  29679. /*                                                                   /*
  29680.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29681.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29682.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29683.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29684.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29685.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29686. )BODY EXPAND(``)
  29687. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29688. %SELECTION ===>_ZCMD                                                           +
  29689. +In the%newsgroup+display, you may type a code in front of a newsgroup name:
  29690.  
  29691.  %S+ - select:      display articles, initially just those you haven't seen yet
  29692.  %N+ - new:         display unseen articles, removing seen ones from display
  29693.  %A+ - all:         display all articles, seen or unseen
  29694.  %R+ - register:    mark the newsgroup as one of your "subscribed" groups
  29695.  %D+ - deregister:  remove the newsgroup from your "subscribed" list
  29696.  %M+ - mark read:   tell the News Viewer you've seen everything in this group
  29697.  %U+ - mark unread: tell the News Viewer you haven't seen anything in this group
  29698.  %Q+ - query:       display newsgroup status (for debugging only)
  29699.  %&A+- &SELEC:      display unseen articles, sorted by subject
  29700.  %&B+- &AL:         display all articles, sorted by subject
  29701. +You may type one of the following commands on the newsgroup command line:
  29702.  %EXTRACT+or%EXT+    - copy the current list of newsgroups into a data set
  29703.  %PRT+or%PRNT+       - print the current list of newsgroups to SYSOUT
  29704.  %LOCATE+or%LOC+or%L+- position display at or near given newsgroup name
  29705.  %FIND string option+- find NEXT, PREV, FIRST or LAST group containing string
  29706.  %ONLY string+       - show only groups containing string (null string for all)
  29707.  %REGISTER+or%REG+   - show registered (subscribed) newsgroups only
  29708.  %ALL+               - show all newsgroups (registered and unregistered)
  29709.  %ORDER Alpha/List+  - order groups alphabetically or by server's active file
  29710. )INIT
  29711.  &A = '$'
  29712.  &B = '@'
  29713.  &SELEC  = '$elect'
  29714.  &AL     = '@ll'
  29715. )PROC
  29716.  &ZUP   = TNNM001
  29717. )END
  29718. ./   ADD NAME=TNNMNNTP
  29719. )ATTR
  29720. /*                                                                   /*
  29721. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29722. /*                                                                   /*
  29723. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29724. /* including the implied warranties of merchantability and fitness,  /*
  29725. /* are expressly denied.                                             /*
  29726. /*                                                                   /*
  29727. /* Provided this copyright notice is included, this software may     /*
  29728. /* be freely distributed and not offered for sale.                   /*
  29729. /*                                                                   /*
  29730. /* Changes or modifications may be made and used only by the maker   /*
  29731. /* of same, and not further distributed.  Such modifications should  /*
  29732. /* be mailed to the author for consideration for addition to the     /*
  29733. /* software and incorporation in subsequent releases.                /*
  29734. /*                                                                   /*
  29735.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29736.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29737.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29738.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29739.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29740.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29741. )BODY EXPAND(``)
  29742. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29743. %SELECTION ===>_ZCMD                                                           +
  29744. %
  29745. % ` `  NNTP (Network News Transfer Protocol)  ` `
  29746. %
  29747. +RFC 977, "A Proposed Standard for the Stream-Based Transmission of News",
  29748.  is the document that describes the Network News Transfer Protocol.
  29749.  
  29750.  You may also wish to read:
  29751.  
  29752.  RFC 1036, "Standard for Interchange of USENET Messages"
  29753.  
  29754.  The%NNTP+option from the main NNMVS menu, or the%NNTP+command from any
  29755.  NNMVS display command line, allows you to communicate directly with
  29756.  the NNTP server using the protocol language defined in RFC 977, subject
  29757.  to the support provided by the news server to which you are connected.
  29758. )INIT
  29759. )PROC
  29760.  &ZUP = TNNM
  29761. )END
  29762. ./   ADD NAME=TNNMOPT
  29763. )ATTR
  29764. /*                                                                   /*
  29765. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29766. /*                                                                   /*
  29767. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29768. /*                                                                   /*
  29769. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29770. /* including the implied warranties of merchantability and fitness,  /*
  29771. /* are expressly denied.                                             /*
  29772. /*                                                                   /*
  29773. /* Provided this copyright notice is included, this software may     /*
  29774. /* be freely distributed and not offered for sale.                   /*
  29775. /*                                                                   /*
  29776. /* Changes or modifications may be made and used only by the maker   /*
  29777. /* of same, and not further distributed.  Such modifications should  /*
  29778. /* be mailed to the author for consideration for addition to the     /*
  29779. /* software and incorporation in subsequent releases.                /*
  29780. /*                                                                   /*
  29781.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29782.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29783.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29784.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29785.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29786.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29787. )BODY EXPAND(``)
  29788. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29789. %SELECTION ===>_ZCMD                                                           +
  29790. %
  29791. % ` `  Options  ` `
  29792. %
  29793. +The user options you set when you enter the OPTIONS command are remembered in
  29794.  your ISPF profile, as is typical of ISPF dialogs.  This is in contrast to
  29795.  newsgroup and article status information, which is stored in your NEWSRC file
  29796.  and not in your ISPF profile.
  29797.  
  29798.  The first set of options specifies handling of the message headers that appear
  29799.  in all news articles.  You may specify whether you want all header lines to be
  29800.  displayed, or just certain ones to be displayed, or certain ones NOT to be
  29801.  displayed, or none to be displayed.  The setting affects article extraction
  29802.  into files as well as viewing.
  29803.  
  29804. +You may specify the frequency at which the News Viewer will update the screen
  29805.  for long-running processes, such as retrieving articles from large newsgroups.
  29806.  
  29807.   %(continued on next page)+
  29808. )INIT
  29809. )PROC
  29810.  &ZUP = TNNM
  29811.  &ZCONT = TNNMOPT2
  29812. )END
  29813. ./   ADD NAME=TNNMOPT2
  29814. )ATTR
  29815. /*                                                                   /*
  29816. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29817. /*                                                                   /*
  29818. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29819. /*                                                                   /*
  29820. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29821. /* including the implied warranties of merchantability and fitness,  /*
  29822. /* are expressly denied.                                             /*
  29823. /*                                                                   /*
  29824. /* Provided this copyright notice is included, this software may     /*
  29825. /* be freely distributed and not offered for sale.                   /*
  29826. /*                                                                   /*
  29827. /* Changes or modifications may be made and used only by the maker   /*
  29828. /* of same, and not further distributed.  Such modifications should  /*
  29829. /* be mailed to the author for consideration for addition to the     /*
  29830. /* software and incorporation in subsequent releases.                /*
  29831. /*                                                                   /*
  29832.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29833.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29834.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29835.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29836.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29837.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29838. )BODY EXPAND(``)
  29839. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29840. %SELECTION ===>_ZCMD                                                           +
  29841. %
  29842. % ` `  Options - Screen Update Frequency ` `
  29843. %
  29844. +You may specify the frequency at which the News Viewer will update the screen
  29845.  for long-running processes.  These include:
  29846.  
  29847.    fetching the list of all newsgroups
  29848.    fetching the headers for unread articles in a newsgroup
  29849.    fetching the current status of registered newsgroup
  29850.  
  29851.  Specifying%ON+is the same as specifying a frequency of zero.  The initial
  29852.  default is%OFF,+but you may want to set it to%ON+or a number to experiment.
  29853.  
  29854.  When you use the%L+or%blank+option to fetch the list of all newsgroups, since
  29855.  the total number is not known, every newsgroup name will flash on the screen as
  29856.  it is read if the Update option is not%OFF.+ For slow terminals, this can
  29857.  greatly slow down the News Viewer; you should always specify%OFF+for slow
  29858.  terminals if you intend to do this.  While article titles are being fetched, if
  29859.  Update is%OFF,+nothing is displayed until all titles are retrieved.  Otherwise,
  29860.  a bar graph showing the progress will be displayed at the indicated interval;
  29861.  if Update is%ON+(the same as zero), the bar graph will be updated as every
  29862.  title is read.  An estimated time to completion will be displayed as well.
  29863. )INIT
  29864. )PROC
  29865.  &ZUP = TNNM
  29866. )END
  29867. ./   ADD NAME=TNNMSERV
  29868. )ATTR
  29869. /*                                                                   /*
  29870. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29871. /*                                                                   /*
  29872. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29873. /* including the implied warranties of merchantability and fitness,  /*
  29874. /* are expressly denied.                                             /*
  29875. /*                                                                   /*
  29876. /* Provided this copyright notice is included, this software may     /*
  29877. /* be freely distributed and not offered for sale.                   /*
  29878. /*                                                                   /*
  29879. /* Changes or modifications may be made and used only by the maker   /*
  29880. /* of same, and not further distributed.  Such modifications should  /*
  29881. /* be mailed to the author for consideration for addition to the     /*
  29882. /* software and incorporation in subsequent releases.                /*
  29883. /*                                                                   /*
  29884.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29885.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29886.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29887.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29888.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29889.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29890. )BODY EXPAND(``)
  29891. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29892. %SELECTION ===>_ZCMD                                                           +
  29893. %
  29894. % ` `  News Servers  ` `
  29895. %
  29896. +Your NNMVS installation may already be configured to start you up with
  29897.  a default news server host.  If so, then you need do nothing special
  29898.  to tell NNMVS to connect to it.  Otherwise, you will need to provide the
  29899.  name of the host running an NNTP news server.
  29900.  
  29901. +Ask your system administrator to tell you the hostname of the machine
  29902.  where an available news server is running.  You may need to ask the
  29903.  administrator of that host to grant you permission to access the news server
  29904.  from the MVS system where the News Viewer will be running as a client.
  29905.  
  29906. +If NNMVS does not recognize the hostname, you may specify an IP address
  29907.  (four numbers separated by periods in the format nn.nn.nn.nn).
  29908. )INIT
  29909. )PROC
  29910.  &ZUP = TNNM
  29911. )END
  29912. ./   ADD NAME=TNNMT,SSI=01010038
  29913. )ATTR
  29914. /*                                                                   /*
  29915. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29916. /*                                                                   /*
  29917. /* SAS enhancements copyright (c) 1992 SAS Institute, Inc.           /*
  29918. /*                                                                   /*
  29919. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29920. /* including the implied warranties of merchantability and fitness,  /*
  29921. /* are expressly denied.                                             /*
  29922. /*                                                                   /*
  29923. /* Provided this copyright notice is included, this software may     /*
  29924. /* be freely distributed and not offered for sale.                   /*
  29925. /*                                                                   /*
  29926. /* Changes or modifications may be made and used only by the maker   /*
  29927. /* of same, and not further distributed.  Such modifications should  /*
  29928. /* be mailed to the author for consideration for addition to the     /*
  29929. /* software and incorporation in subsequent releases.                /*
  29930. /*                                                                   /*
  29931.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29932.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29933.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29934.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29935.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29936.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29937. )BODY EXPAND(``)
  29938. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29939. %SELECTION ===>_ZCMD                                                           +
  29940. +In the%article+display, you may type these codes in front of an article number:
  29941.  %S+ - select:      browse the article text
  29942.  %E+ - extract:     copy the article into a data set
  29943.  %P+ - print:       print the article to SYSOUT
  29944.  %M+ - mark read:   tell the News Viewer you've already seen this article
  29945.  %U+ - mark unread: tell the News Viewer you haven't seen this article
  29946.  %F+ - followup:    post a follow-up news article, news server permitting
  29947.  %R+ - reply:       send private mail to the originator of the news article
  29948.  %C+ - cancel:      send article cancel request to server (author must be you)
  29949.  %Q+ - query:       display article status (for debugging only)
  29950.  
  29951. +You may type one of the following commands on the article display command line:
  29952. %LOCATE+or%LOC+or%L+  - position display at or near given article number
  29953. %EXTRACT+or%EXT+      - copy titles or text of all articles into a data set
  29954. %PRT+or%PRNT+         - print titles or text of all articles to SYSOUT
  29955. %TITLES+or%TITLE+     - retrieve titles of all articles in table from the server
  29956. %QUERY+               - display newsgroup status (for debugging only)
  29957. %FIND string option+  - find NEXT, PREV, FIRST or LAST article with "string"
  29958. %ONLY string       +  - limit display to articles with "string" in the subject
  29959. %MARKALL+or%UNMARKALL+- mark all articles in this newsgroup read or unread
  29960. %SORT Subject/Number +- sort article display by subject or by article number
  29961. )INIT
  29962. )PROC
  29963.  &ZUP   = TNNM001
  29964.  &TNNMTHR = &Z
  29965. )END
  29966. ./   ADD NAME=TNNM001,SSI=01000018
  29967. )ATTR
  29968. /*                                                                   /*
  29969. /* Copyright (c) The Charles Stark Draper Laboratory, Inc., 1992     /*
  29970. /*                                                                   /*
  29971. /* This software is provided on an "AS IS" basis.  All warranties,   /*
  29972. /* including the implied warranties of merchantability and fitness,  /*
  29973. /* are expressly denied.                                             /*
  29974. /*                                                                   /*
  29975. /* Provided this copyright notice is included, this software may     /*
  29976. /* be freely distributed and not offered for sale.                   /*
  29977. /*                                                                   /*
  29978. /* Changes or modifications may be made and used only by the maker   /*
  29979. /* of same, and not further distributed.  Such modifications should  /*
  29980. /* be mailed to the author for consideration for addition to the     /*
  29981. /* software and incorporation in subsequent releases.                /*
  29982. /*                                                                   /*
  29983.  ^ TYPE(TEXT) INTENS(HIGH) COLOR(BLUE) HILITE(REVERSE)
  29984.  # TYPE(TEXT) INTENS(LOW)  COLOR(TURQ)
  29985.  \ TYPE(TEXT) INTENS(HIGH) COLOR(YELLOW)
  29986.  ! TYPE(TEXT) INTENS(HIGH) COLOR(RED)
  29987.  $ TYPE(TEXT) INTENS(LOW)  COLOR(GREEN)
  29988.  ~ TYPE(TEXT) INTENS(HIGH) COLOR(WHITE)
  29989. )BODY EXPAND(``)
  29990. %TUTORIAL -`-`-  MVS Network News Viewer -`-`- TUTORIAL
  29991. %SELECTION ===>_ZCMD                                                           +
  29992. %
  29993. +There are three kinds of displays created by the News Viewer:
  29994.  
  29995. %   Newsgroups+ - which allows you to select newsgroups by name
  29996. %   Articles  + - which allows you to select articles by name
  29997. %   Text      + - which allows you to browse article text or NNTP output
  29998.  
  29999. +Additional commands are available specific to each of the above modes.
  30000.  
  30001. +The following topics will be displayed next, or may be selected by number:
  30002.  
  30003. %   1 + - Commands Available From All Displays
  30004. %   2 + - The Newsgroup Display (Available Selection Codes and Commands)
  30005. %   3 + - The Article Display   (Available Selection Codes and Commands)
  30006. %   4 + - The Text Display      (Available Commands)
  30007. %   5 + - Specifying User Options
  30008. )INIT
  30009. )PROC
  30010.  &ZSEL = TRANS(&ZCMD 1,TNNMC 2,TNNMG 3,TNNMT 4,TNNMB1 5,TNNMOPT *,?)
  30011.  &ZUP = TNNM
  30012. )END
  30013. ./ ENDUP 
  30014. ?!
  30015.